﻿#include "CampMgr.h"
#include "base/core/gamemath.h"
#include "CenterService.h"
#include "ProtoBuffer/AllProtocol.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "Duplicate/CenterDuplicateMgr.h"
#include "Arena/ArenaMgr.h"
#include "ChatCenter/ChatCenter.h"
#include "Team/TeamManager.h"
#include "Union/UnionMgr.h"
#include "MailCenter/MailManager.h"
#include "MirrorMgr/MirrorMgr.h"
#include "RelationMgr/RelationMgr.h"
#include "Team/Team.h"
#include "RankingList/RankingListMgr.h"
#include "SceneMgr/CenterSceneMrg.h"
#include "Common/TableData/CampOfficialCfg.h"
#include "Common/TableData/CampGodsCfg.h"
#include "Common/TableData/CampFeteCfg.h"
#include "Common/TableData/CampKnighthoodCfg.h"
#include "Common/TableData/CampDestiny_choiceCfg.h"
#include "Common/TableData/CampFree_choiceCfg.h"
#include "Common/TableData/CampConstantCfg.h"
#include "Common/TableData/MailMailCfg.h"
#include "Common/TableData/ConstantConstantCfg.h"
#include "Common/TableData/FunctionunlockFunctionUnlockCfg.h"
#include "Common/Utility/ServerTime.h"
#include "Common/Utility/TimeUtility.h"
#include "Common/ComTypeDefine.h"
#include "base/core/random.h"
#include <functional>
#include <algorithm>

#ifdef _MSC_VER
#pragma warning(disable:4100)
#pragma warning(disable:4244)
#pragma warning(disable:4102)
#endif

using namespace std;

uint32_t CampMgr::CampElecMinLightKnight = 0;
uint32_t CampMgr::CampElecMinDarkKnight = 0;
uint32_t CampMgr::CampElecMinLightOfficial = 0;
uint32_t CampMgr::CampElecMinDarkOfficial = 0;
uint32_t CampMgr::CampPublishNoticeCostDiamd = 0;
uint32_t CampMgr::CampLightLeaderNpc = 0;
uint32_t CampMgr::CampDarkLeaderNpc = 0;
uint32_t CampMgr::CampElectionCostPrestige = 0;
uint32_t CampMgr::CampElectionCostDiamond = 0;
uint32_t CampMgr::CampVoteCostPrestige = 0;
int16_t CampMgr::CampElectionMinLevel = 0;
uint32_t CampMgr::CampNoticeCDTime = 0;
uint32_t CampMgr::CampChangeCDTime = 0;
uint32_t CampMgr::CampEleOpenTick = 0;
uint32_t CampMgr::CampEleCloseTick = 0;
uint32_t CampMgr::CampVoteOpenTick = 0;
uint32_t CampMgr::CampVoteCloseTick = 0; 
uint32_t CampMgr::CampVoteCloseHour = 0;

CampMgr::CampMgr() :m_bCampNeedSave(false), m_bFinishLoad(false), m_lastSaveTime(0), m_pCharacterCampPool(nullptr)
{
	m_vecAllCamp.resize(ECamp_Type_Limit, nullptr);
}

CampMgr::~CampMgr()
{}

bool CampMgr::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return false;
	}
	pMessageDispatch->registerDBProxyHandler(EMODULE_ID_CAMP,this);
	pMessageDispatch->registerClientHandler(EMODULE_ID_CAMP, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_CAMP, this);

	m_pCharacterCampPool = new ObjectPool<CharacterCamp>(200, false);
	MMOLOG_PROCESS_ERROR_RET(nullptr != m_pCharacterCampPool,false);

	//阵营
	m_vecAllCamp[ECamp_Type_Light] = new Camp(ECamp_Type_Light, CAMP_LIGHT_ID);
	MMOLOG_PROCESS_ERROR_RET(nullptr != m_vecAllCamp[ECamp_Type_Light], false);

	m_vecAllCamp[ECamp_Type_Dark] = new Camp(ECamp_Type_Dark, CAMP_DRAK_ID);
	MMOLOG_PROCESS_ERROR_RET(nullptr != m_vecAllCamp[ECamp_Type_Dark], false);


	m_setCharacterCampNeedSave.clear();
	m_mapWaitCampNotice.clear();
	m_noneCampChars.clear();

	g_GetActiveCharacterMgr()->AddCharacterObserver(this);

	g_GetTimerAxis()->SetTimer(ETimer_ID_Load_Camp, 2 * 1000, this);
	//g_GetTimerAxis()->SetTimer(ETimer_ID_Update_Camp, 60 * 1000, this);
	g_GetTimerAxis()->SetTimer(ETimer_ID_Conn_Logic, 2 * 1000, this);

	const ConstantConstantCfgInfo *pCampElecMinLightKnightCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampElecMinLightKnight);
	if (nullptr == pCampElecMinLightKnightCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampElecMinLightKnightCfg = nullptr.. failed....constId:%d", EArg_CampElecMinLightKnight);
		return false;
	}
	const ConstantConstantCfgInfo *pCampElecMinDarkKnightCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampElecMinDarkKnight);
	if (nullptr == pCampElecMinDarkKnightCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampElecMinDarkKnightCfg = nullptr.. failed....constId:%d", EArg_CampElecMinDarkKnight);
		return false;
	}
	const ConstantConstantCfgInfo *pCampElecMinLightOfficialCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampElecMinLightOfficial);
	if (nullptr == pCampElecMinLightOfficialCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampElecMinLightOfficialCfg = nullptr.. failed....constId:%d", EArg_CampElecMinLightOfficial);
		return false;
	}
	const ConstantConstantCfgInfo *pCampElecMinDarkOfficialCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampElecMinDarkOfficial);
	if (nullptr == pCampElecMinDarkOfficialCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampElecMinDarkOfficialCfg = nullptr.. failed....constId:%d", EArg_CampElecMinDarkOfficial);
		return false;
	}
	const ConstantConstantCfgInfo *pCampPublishNoticeCostDiamdlCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_PublishCampNoticePrice);
	if (nullptr == pCampPublishNoticeCostDiamdlCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampPublishNoticeCostDiamdlCfg = nullptr.. failed....constId:%d", EArg_PublishCampNoticePrice);
		return false;
	}

	const ConstantConstantCfgInfo *pCampLightLeaderNpcCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampLightLeaderNpc);
	if (nullptr == pCampLightLeaderNpcCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampLightLeaderNpcCfg = nullptr.. failed....constId:%d", EArg_CampLightLeaderNpc);
		return false;
	}
	const ConstantConstantCfgInfo *pCampDarkLeaderNpcCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampDarkLeaderNpc);
	if (nullptr == pCampDarkLeaderNpcCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampDarkLeaderNpcCfg = nullptr.. failed....constId:%d", EArg_CampDarkLeaderNpc);
		return false;
	}

	const ConstantConstantCfgInfo *pCampElectionCostPrestigeCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampElectionCostPrestige);
	if (nullptr == pCampElectionCostPrestigeCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampElectionCostPrestigeCfg = nullptr.. failed....constId:%d", EArg_CampElectionCostPrestige);
		return false;
	}

	const ConstantConstantCfgInfo *pCampElectionCostDiamondCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampElectionCostDiamond);
	if (nullptr == pCampElectionCostDiamondCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampElectionCostDiamondCfg = nullptr.. failed....constId:%d", EArg_CampElectionCostDiamond);
		return false;
	}

	const ConstantConstantCfgInfo *pCampVoteCostPrestigeCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampVoteCostPrestige);
	if (nullptr == pCampVoteCostPrestigeCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampVoteCostPrestigeCfg = nullptr.. failed....constId:%d", EArg_CampVoteCostPrestige);
		return false;
	}

	const ConstantConstantCfgInfo *pCampElectionMinLevelCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampElectionMinLevel);
	if (nullptr == pCampElectionMinLevelCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampElectionMinLevelCfg = nullptr.. failed....constId:%d", EArg_CampElectionMinLevel);
		return false;
	}

	const ConstantConstantCfgInfo *pCampNoticeCDTimeCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_CampNoticeCDTime);
	if (nullptr == pCampNoticeCDTimeCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampNoticeCDTimeCfg = nullptr.. failed....constId:%d", EArg_CampNoticeCDTime);
		return false;
	}

	const CampConstantCfgMap *pCampConstMap = g_GetCampConstantCfgTable()->GetCampConstantCfgMap();
	if (nullptr == pCampConstMap || pCampConstMap->size() != 1)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampConstMap = nullptr || pCampConstMap->size() != 1.. failed....");
		return false;
	}
	const CampConstantCfgInfo *pCampConstCfg = &(pCampConstMap->begin())->second;
	if (nullptr == pCampConstCfg)
	{
		LogErrFmtPrint("[center]CampMgr::Init pCampConstCfg = nullptr.. failed....");
		return false;
	}

	std::vector<int32_t> vEleOpenTimeVec;
	CommonApi::SplitStrToVecInt(pCampConstCfg->electionopenTime, ":", &vEleOpenTimeVec);
	std::vector<int32_t> vEleCloseTimeVec;
	CommonApi::SplitStrToVecInt(pCampConstCfg->electionclosedTime, ":", &vEleCloseTimeVec);
	std::vector<int32_t> vVoteOpenTimeVec;
	CommonApi::SplitStrToVecInt(pCampConstCfg->BallotopenTime, ":", &vVoteOpenTimeVec);
	std::vector<int32_t> vVoteCloseTimeVec;
	CommonApi::SplitStrToVecInt(pCampConstCfg->BallotclosedTime, ":", &vVoteCloseTimeVec);
	if (vEleOpenTimeVec.size() != 2 || vEleCloseTimeVec.size() != 2 || vVoteOpenTimeVec.size() != 2 || vVoteCloseTimeVec.size() != 2)
	{
		LogErrFmtPrint("[center]CampMgr::Init vEleOpenTimeVec.size() != 2... failed....");
		return false;
	}

	CampEleOpenTick = pCampConstCfg->electionopenCycle * 24 * 60 + vEleOpenTimeVec.at(0) * 60 + vEleOpenTimeVec.at(1);
	CampEleCloseTick = pCampConstCfg->electionclosedCycle * 24 * 60 + vEleCloseTimeVec.at(0) * 60 + vEleCloseTimeVec.at(1);

	CampVoteOpenTick = pCampConstCfg->BallotopenCycle * 24 * 60 + vVoteOpenTimeVec.at(0) * 60 + vVoteOpenTimeVec.at(1);
	CampVoteCloseTick = pCampConstCfg->BallotclosedCycle * 24 * 60 + vVoteCloseTimeVec.at(0) * 60 + vVoteCloseTimeVec.at(1);
	CampVoteCloseHour = vVoteCloseTimeVec.at(0);

	CampElecMinLightKnight = pCampElecMinLightKnightCfg->constantdata;
	CampElecMinDarkKnight = pCampElecMinDarkKnightCfg->constantdata;
	CampElecMinLightOfficial = pCampElecMinLightOfficialCfg->constantdata;
	CampElecMinDarkOfficial = pCampElecMinDarkOfficialCfg->constantdata;
	CampPublishNoticeCostDiamd = pCampPublishNoticeCostDiamdlCfg->constantdata;
	CampLightLeaderNpc = pCampLightLeaderNpcCfg->constantdata;
	CampDarkLeaderNpc = pCampDarkLeaderNpcCfg->constantdata;
	CampElectionCostPrestige = pCampElectionCostPrestigeCfg->constantdata;
	CampElectionCostDiamond = pCampElectionCostDiamondCfg->constantdata;
	CampVoteCostPrestige = pCampVoteCostPrestigeCfg->constantdata;
	CampElectionMinLevel = pCampElectionMinLevelCfg->constantdata;
	CampNoticeCDTime = pCampNoticeCDTimeCfg->constantdata;
	CampChangeCDTime = pCampConstCfg->ChangeCampCD * 24 * 3600;
	return true;
}

void CampMgr::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr != pMessageDispatch)
	{
		pMessageDispatch->unregisterDBProxyHandler(EMODULE_ID_CAMP);
		pMessageDispatch->unregisterClientHandler(EMODULE_ID_CAMP);
		pMessageDispatch->unregisterServerHandler(EMODULE_ID_CAMP);
	}

	g_GetTimerAxis()->KillAllTimer(this);
	g_GetTimerAxis()->KillAllFixTimer(this);

	g_GetActiveCharacterMgr()->RemoveCharacterObserver(this);

	for (int32_t i = ECamp_Type_None; i < ECamp_Type_Limit; ++i)
	{
		MMO_DELETE(m_vecAllCamp[i]);
	}
	m_vecAllCamp.clear();

	MapAllCharacterCamp::iterator iterDel = m_mapAllCharacterCamp.begin();
	for (; iterDel != m_mapAllCharacterCamp.end(); ++iterDel)
	{
		CharacterCamp *pData = iterDel->second;
		FreeCharacterCampObj(pData);
	}

	m_mapAllCharacterCamp.clear();
	m_mapWaitCampNotice.clear();
	m_bFinishLoad = false;

	MMO_DELETE(m_pCharacterCampPool);
}

void CampMgr::SaveDB(bool close)
{
	SaveCampDataReq(close);
	SaveCharacterCampReq(close);
}

void CampMgr::onCharacterLogin(ActiveCharacter *pOnlineCharacter)
{
	if (!pOnlineCharacter)	return;
	//请求加载角色阵营数据（详细数据）
	CharacterCampDBReq req;
	req.set_charid(pOnlineCharacter->GetCharID());
	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_CAMP, DBPROXY_PROTOCOL_CAMP_PLAYER_GET_REQ, &req))
	{
		LogErrFmtPrint("[center] CampMgr::onCharacterLogin....SendDataToDBProxy failed....charid:%lu ", pOnlineCharacter->GetCharID());
	}

}

void CampMgr::onCharacterLogout(ActiveCharacter *pOnlineCharacter)
{
	if (!pOnlineCharacter)	return;
	SaveSingleCharacterCamp(pOnlineCharacter->GetCharID());
	MapAllCharacterCamp::iterator iter = m_mapAllCharacterCamp.find(pOnlineCharacter->GetCharID());
	if (iter != m_mapAllCharacterCamp.end())
	{
		CharacterCamp *pCharCamp = iter->second;
		if (nullptr == pCharCamp)	return;

		pCharCamp->Clear();
		FreeCharacterCampObj(pCharCamp);
		m_mapAllCharacterCamp.erase(iter);
	}
	else
	{
		m_noneCampChars.erase(pOnlineCharacter->GetCharID());
	}
}

void CampMgr::onCharacterDisconnect(ActiveCharacter *pOnlineCharacter)
{
	onCharacterLogout(pOnlineCharacter);
}

void CampMgr::onCharacterUpdate(ActiveCharacter *pOnlineCharacter)
{
	if (!pOnlineCharacter)	return;
	if (pOnlineCharacter->GetLastAttrUpdate(C_LEVEL) > 0)
	{
		OfflineCharacterData * pCharacter = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pOnlineCharacter->GetCharID());
		if (!pCharacter || pCharacter->GetLevel() < 20)
		{
			return;
		}

		Camp *pCamp = GetCamp(pCharacter->GetCampID());
		if (pCamp)
		{
			pCamp->RankChange(pCharacter, ECamp_Sort_Type_Level);
		}
	}
	if (pOnlineCharacter->GetLastAttrUpdate(C_FIGHT_POWER) > 0)
	{
		OfflineCharacterData * pCharacter = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pOnlineCharacter->GetCharID());
		if (!pCharacter || pCharacter->GetLevel() < 20)
		{
			return;
		}

		Camp *pCamp = GetCamp(pCharacter->GetCampID());
		if (pCamp)
		{
			pCamp->RankChange(pCharacter, ECamp_Sort_Type_Fight);
		}
	}
	if (pOnlineCharacter->GetLastAttrUpdate(C_OFFICIAL) > 0)
	{
		OfflineCharacterData * pCharacter = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pOnlineCharacter->GetCharID());
		if (!pCharacter || pCharacter->GetLevel() < 20)
		{
			return;
		}

		Camp *pCamp = GetCamp(pCharacter->GetCampID());
		if (pCamp)
		{
			pCamp->RankChange(pCharacter, ECamp_Sort_Type_Official);
		}
	}
	if (pOnlineCharacter->GetLastAttrUpdate(C_KNIGHT) > 0)
	{
		OfflineCharacterData * pCharacter = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pOnlineCharacter->GetCharID());
		if (!pCharacter || pCharacter->GetLevel() < 20)
		{
			return;
		}

		Camp *pCamp = GetCamp(pCharacter->GetCampID());
		if (pCamp)
		{
			pCamp->RankChange(pCharacter, ECamp_Sort_Type_Knight);
		}
	}
}

void CampMgr::onCharacterDel(OfflineCharacterData *pOffLineCharacter)
{
	if (!pOffLineCharacter)	return;
	CharIDType charId = pOffLineCharacter->GetCharID();
	Camp *pCamp = GetCamp(pOffLineCharacter->GetCampID());
	if (nullptr == pCamp)
		return;

	//首领角色删角处理
	if (charId == pCamp->LeaderID())
	{
		pCamp->LeaderID(0);
		UpdateCampLeaderToLogic(pCamp->CampID());
	}

	SET_UINT64 *pMem = pCamp->Chars();
	if (nullptr == pMem)
		return;

	//从旧阵营中删除
	pMem->erase(charId);
	//阵营榜单处理
	pCamp->DelChars(pOffLineCharacter);
	//退出竞选
	pCamp->DelCandi(charId);	
}

void CampMgr::onCharacterFacadeUpdate(OfflineCharacterData *pOffLineCharacter)
{
	if (!pOffLineCharacter)	return;
	UpdateCampLeaderToLogic(pOffLineCharacter->GetCampID(), pOffLineCharacter->GetCharID());
}

const SET_UINT64 *CampMgr::GetCampAllMember(int8_t byCampID)
{
	Camp *pCamp = GetCamp(byCampID);
	if (nullptr != pCamp)
	{
		return pCamp->Chars();
	}
	return &m_noneCampChars;
}

void CampMgr::onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case DBPROXY_PROTOCOL_CAMP_PLAYER_GET_RSP:
		{
			CharacterCampDBRsp rsp;
			if (!rsp.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
			{
				LogErrFmtPrint("[center] CharacterCampDBRsp parse failed... ");
				return;
			}
			LoadCharacterCampRet(rsp);
		}
		break;
	case DBPROXY_PROTOCOL_LOAD_CAMP_MIRROR_DATA_CALL_BACK:
		{
			OnDBLoadCampMirrorCallBack(package);
		}
		break;
	default:
		break;
	}
}

void CampMgr::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_ID_Load_Camp:
		{
			if (g_GetCenterService()->IsConnectDBProxy() && g_GetOfflineCharacterDataMgr()->IsFinishLoad())
			{
				LoadCampDataReq();
				g_GetTimerAxis()->KillTimer(ETimer_ID_Load_Camp, this);
			}
		}
		break;
	/*case ETimer_ID_Update_Camp:
		{
			if (m_bFinishLoad)
			{
				CheckElection();
				SaveCampDataReq();
				SaveCharacterCampReq();
			}
		}
		break;*/
	case ETimer_ID_Conn_Logic:	//检测中心服与阵营地图所在逻辑服建立通信
		{
			if (m_bFinishLoad)
			{
				Camp *pLightCamp = GetCamp(ECamp_Type_Light);
				Camp *pDarkCamp = GetCamp(ECamp_Type_Dark);
				if (nullptr == pLightCamp || nullptr == pDarkCamp)
				{
					LogErrFmtPrint("[center] CampMgr::OnTimer...nullptr == pLightCamp || nullptr == pDarkCamp...");
					return;
				}

				const CampFree_choiceCfgInfo *pLightinfo = g_GetCampFree_choiceCfgTable()->GetCampFree_choiceCfgInfo(pLightCamp->ConfigID());
				const CampFree_choiceCfgInfo *pDarkinfo = g_GetCampFree_choiceCfgTable()->GetCampFree_choiceCfgInfo(pDarkCamp->ConfigID());
				if (nullptr == pLightinfo || nullptr == pDarkinfo)
				{
					LogErrFmtPrint("[center] CampMgr::OnTimer...nullptr == pLightinfo || nullptr == pDarkinfo...");
					return;
				}

				uint32_t logicId1 = g_GetCenterSceneMgr()->GetLogicIdByMapId(pLightinfo->mapId);
				uint32_t logicId2 = g_GetCenterSceneMgr()->GetLogicIdByMapId(pDarkinfo->mapId);
				if (0 == logicId1 || 0 == logicId2)
				{
					LogErrFmtPrint("[center] CampMgr::OnTimer...0 == logicId1 || 0 == logicId2...lightMapID:%d,darkMapID:%d,logicId1:%d,logicId2:%d,", pLightinfo->mapId, pDarkinfo->mapId, logicId1, logicId2);
					return;
				}

				if (nullptr != g_GetCenterService()->GetLogicSession(logicId1) && nullptr != g_GetCenterService()->GetLogicSession(logicId2))
				{
					UpdateCampLeaderToLogic(ECamp_Type_Light);
					UpdateCampLeaderToLogic(ECamp_Type_Dark);
					g_GetTimerAxis()->KillTimer(ETimer_ID_Conn_Logic, this);
				}
			}
		}
		break;
	default:
		break;
	}
}
void CampMgr::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case LOGIC_TO_CENTER_CAMP_CHECK_NOTICE_COST_RSP:
		LogicToCenter_CheckNoticeCost(package);
		break;
	case LOGIC_TO_CENTER_CAMP_CHECK_ELECTION_COST_RSP:
		LogicToCenter_CheckElectionCost(package);
		break;
	case LOGIC_TO_CENTER_CAMP_CHECK_VOTE_RSP:
		LogicToCenter_CheckVote(package);
		break;
	case LOGIC_TO_CENTER_CAMP_CHECK_PRAY_COST_RSP:
		LogicToCenter_CheckPrayCost(package);
		break;
	case LOGIC_TO_CENTER_CAMP_TOTIFY_EVENT:
		LogicToCenter_Notify(package);
		break;
	case LOGIC_TO_CENTER_CAMP_ADD_CAMP_ATTR:
		LogicToCenter_AddAttr(package);
		break;
	case LOGIC_TO_CENTER_ARENA_CAMP_CHALL_RESULT:
		LogicToCenter_CampChallenge(package);
		break;
	case LOGIC_TO_CENTER_CAMP_PUSH_PRAY_INFO:
		LogicToCenter_CampPushPrayInfo(package);
		break;
	case LOGIC_TO_CENTER_CAMP_CHECK_CHANGE_RSP:
		LogicToCenter_CampChangeCost(package);
		break;
	}
}
void CampMgr::onClientMessage(uint32_t actionId, RECV_PACKAGE& package, uint64_t Id /* = 0 */)
{
	UNPACK_MESSAGE_CHAR_ID(package);
	switch (actionId)
	{
	case CLIENT_TO_CENTER_CAMP_GET_DATA:
		HandClient_CampGetData(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_DESTINY:
		HandClient_GetDestinyID(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_JOIN:
		HandClient_JoinCamp(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_INFO:
		HandClient_CampInfo(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_HONOR_INFO:
		HandClient_CampHonor(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_RANK_INFO:
		HandClient_CampRank(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_PUBLISH_NOTICE:
		HandClient_PublishNotice(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_DIVIDEND:
		HandClient_CampDevidend(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_ELECTION:
		HandClient_CampElection(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_VOTE:
		HandClient_CampVote(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_ELECTION_INFO:
		HandClient_CampElectionRank(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_CHALLENGE:
		HandClient_CampChallenge(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_KNIGHT_UP:
		HandClient_CampKnightUp(charId, package);
		break;
	case CLIENT_TO_CENTER_CAMP_CHANGE:
		HandClient_CampChange(charId, package);
		break;
	default:
		break;
	}
}

bool CampMgr::LoadCampDataReq()
{
	GlobalDBRequst req;
	req.set_type_id(EGlobalType_Camp);
	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_GLOBAL_GET_REQ, &req))
	{
		LogErrFmtPrint("[center] CampMgr::LoadCampDataReq...SendDataToDBProxy failed...");
	}
	return true;
}

bool CampMgr::LoadCampDataRet(const string &data)
{
	if (data.length() <= 0)
	{
		m_bFinishLoad = true;
		m_bCampNeedSave = true;		//数据库没有记录，第一次创建需要保存
		return true;
	}

	AllCampDBData protocamp;
	if (!protocamp.ParseFromArray(data.c_str(), (int32_t)data.length()))
	{
		MMOLOG_FMT_ERROR("[center] LoadCampDataRet parase failed...");
		return false;
	}

	uint64_t last_time = protocamp.last_save_time();
	uint64_t cur_time = g_GetGlobalServerTime()->UnixSec();
	
	int32_t nsize = protocamp.all_camp_data_size();
	for (int32_t i = 0; i < nsize; ++i)
	{
		const SingleCampDBData &protoCampData = protocamp.all_camp_data(i);
		Camp *pCamp = GetCamp((int8_t)protoCampData.camp_id());
		if (nullptr == pCamp)
		{
			LogErrFmtPrint("[center] CampMgr::LoadCampDataRet...nullptr == pCamp...camp_id:%d ",protoCampData.camp_id());
			continue;
		}

		CampCandidateVec *pElectionRank = pCamp->GetElectionRank();
		CampGodsInfoMap *pGodsInfoMap = pCamp->GetGodsInfo();
		MAP_UINT64_UINT32 &allOfficialMap = pCamp->GetOfficialMap();
		if (nullptr == pElectionRank || nullptr == pGodsInfoMap)
		{
			LogErrFmtPrint("[center] CampMgr::LoadCampDataRet...camp rank ptr is null...camp_id:%d ", protoCampData.camp_id());
			continue;
		}
		pCamp->CampID((int8_t)protoCampData.camp_id());
		pCamp->LeaderID(protoCampData.leader_id());
		pCamp->LastFresh(protoCampData.last_fresh());
		pCamp->LastNotice(protoCampData.last_notice());
		pCamp->Notice(protoCampData.notice().c_str());

		const CampElectionRankDBData &protoElectionRank = protoCampData.election_rank();
		int32_t len = protoElectionRank.rank_size();
		for (int32_t n = 0; n < len; ++n)
		{
			const CampElectionRankInfo &protoRank = protoElectionRank.rank(n);
			OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(protoRank.char_id());
			if (nullptr == pOffline)
			{
				LogInfoFmtPrint("[center] CampMgr::LoadCampDataRet...camp member not found..maybe delete...charid:%lu ", protoRank.char_id());
				continue;
			}
			
			SCampCandidateInfo info;
			SafeCopyString(info.szName, sizeof(info.szName), protoRank.name().c_str());
			info.nCharId = protoRank.char_id();
			info.nLevel = protoRank.level();
			info.prof = protoRank.prof();
			info.sex = protoRank.sex();
			info.votes = protoRank.votes();
			info.votesGain = protoRank.votes_gain();
			info.num = protoRank.num();
			info.lastVoteTick = protoRank.lastvotetick();
			SafeCopyString(info.declare, sizeof(info.declare), protoRank.declare().c_str());
			pElectionRank->push_back(info);
		}

		pGodsInfoMap->clear();
		const CampGodsInfoDBData &protoGodsInfo = protoCampData.gods_info();
		len = protoGodsInfo.info_size();
		for (int32_t n = 0; n < len; ++n)
		{
			const CampGodsInfo &godsInfo = protoGodsInfo.info(n);
			SCampGodsInfo info;
			info.num = godsInfo.num();
			pGodsInfoMap->insert(std::make_pair(godsInfo.gods_id(), info));
		}

		allOfficialMap.clear();
		const CampOfficialInfoDBData &protoOfficialInfo = protoCampData.official_info();
		len = protoOfficialInfo.info_size();
		for (int32_t n = 0; n < len; ++n)
		{
			const CampOfficialInfo &officialInfo = protoOfficialInfo.info(n);
			allOfficialMap[officialInfo.charid()] = officialInfo.official();
		}

		//上次关服时间在投票结束前，要执行一次选举逻辑
		if (TimeUtility::CheckWeekUpdate(cur_time, last_time, CampVoteCloseHour))
			ElectionOver(pCamp);
		else
			UpdateCampLeaderToLogic(pCamp->CampID());
	}

	m_bFinishLoad = true;
	LogDebugFmtPrint("[center] Load Camp Data finished....");

	//数据加载完成后排下序
	Camp *pLightCamp = GetCamp(ECamp_Type_Light);
	if (nullptr != pLightCamp)
	{
		pLightCamp->CampRank();
	}
	Camp *pDarkCamp = GetCamp(ECamp_Type_Dark);
	if (nullptr != pDarkCamp)
	{
		pDarkCamp->CampRank();
	}

	return true;
}

void CampMgr::LoadCharacterCampRet(CharacterCampDBRsp &rsp)
{
	CharIDType charId = rsp.charid();
	if (RET_SUCCESS != rsp.retcode())
	{
		LogErrFmtPrint("[center] CampMgr::LoadCharacterCampRet....retcode:%d ,charid:%lu", rsp.retcode(), charId);
		return;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		LogErrFmtPrint("[center] CampMgr::LoadCharacterCampRet....can not find char OfflineCharacterData, charid:%lu ", charId);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		m_noneCampChars.insert(charId);
		return;
	}

	CharacterCamp *pCharCamp = GetCharacterCamp(charId);
	if (nullptr == pCharCamp)
	{
		pCharCamp = MakeCharacterCampObj();
		if (nullptr == pCharCamp)
		{
			LogErrFmtPrint("[center] CampMgr::LoadCharacterCampRet....nullptr == pCharCamp...charid:%lu ", charId);
			return;
		}
	}

	pCharCamp->Clear();
	pCharCamp->CharID(charId);
	if (rsp.has_info())
	{
		const CharacterCampDBData &charData = rsp.info();
		pCharCamp->LoadData(charData);
		LogDebugFmtPrint("CharacterCamp::LoadCharacterCampRet...charid:%lu, m_nDividendTime:%lu, m_nDividendFlag:%d ", charId, pCharCamp->DividendTime(), pCharCamp->DividendFlag());

		uint64_t nCurSec = g_GetGlobalServerTime()->UnixSec();
		if (TimeUtility::CheckDayUpdate(nCurSec, pCharCamp->LastLogout()))
		{
			FirstLoginDay(charId);
		}
		if (TimeUtility::CheckWeekUpdate(nCurSec, pCharCamp->LastLogout(), CampVoteCloseHour))
		{
			pCharCamp->ResetEleInfo();
			m_setCharacterCampNeedSave.insert(charId);
			pCharCamp->NeedSave(true);
		}
		if (TimeUtility::CheckWeekUpdate(nCurSec, pCharCamp->DividendTime()))
		{
			//上次阵营分红到现在，已经经过了一周，需要重置领取标志
			pCharCamp->DividendFlag(false);
			pCharCamp->DividendTime(nCurSec);
			m_setCharacterCampNeedSave.insert(charId);
			pCharCamp->NeedSave(true);
			LogDebugFmtPrint("CharacterCamp::LoadCharacterCampRet 11...charid:%lu, m_nDividendTime:%lu, m_nDividendFlag:%d ", charId, pCharCamp->DividendTime(), pCharCamp->DividendFlag());
		}

		//阵营影响的一级属性
		LogicToCenter_CampAttChange attChange;
		attChange.set_char_id(charId);
		CampPrayInfoMap &prayMap = pCharCamp->GetPrayMap();
		prayMap.clear();
		size_t size = charData.prayinfo_size();
		for (size_t i = 0; i != size; ++i)
		{
			const CharacterCampPrayInfo &prayProto = charData.prayinfo(i);
			SCampPrayInfo prayInfo;
			prayInfo.devout = prayProto.devout();
			size_t att_size = prayProto.attinfo_size();
			for (size_t i = 0; i != att_size; ++i)
			{
				prayInfo.attrMap[prayProto.attinfo(i).attrid()] = prayProto.attinfo(i).att();
				LogicToCenter_CampAttChange::Attr *pAttr = attChange.add_att();
				pAttr->set_attrid(prayProto.attinfo(i).attrid());
				pAttr->set_att(prayProto.attinfo(i).att());
			}
			prayMap[prayProto.godid()] = prayInfo;
		}
		g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CAMP_ATT_CHANGE, &attChange);
	}
	else
	{
		//数据库还没有角色阵营数据，需要保存角色阵营的数据
		m_setCharacterCampNeedSave.insert(charId);
		pCharCamp->NeedSave(true);
	}

	m_mapAllCharacterCamp[pCharCamp->CharID()] = pCharCamp;
	CheckOfficial(pOffline, pCamp);
	pCamp->AddActiveChars(charId);
}

void CampMgr::SaveCharacterCampReq(bool close)
{
	auto iter = m_setCharacterCampNeedSave.begin();
	for (; iter != m_setCharacterCampNeedSave.end(); ++iter)
	{
		//这里单个去保存，多个一起保存容易造成一次发送的数据超长
		CharIDType nCharID = (*iter);
		SaveSingleCharacterCamp(nCharID, close);
	}
	m_setCharacterCampNeedSave.clear();
}

void CampMgr::SaveSingleCharacterCamp(CharIDType nCharID, bool close)
{
	CharacterCamp *pCharCamp = GetCharacterCamp(nCharID);
	if (nullptr == pCharCamp)
		return;

	//if (!close && !pCharCamp->NeedSave())
	//	return;

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(nCharID);
	if (nullptr == pOffline)
	{
		LogErrFmtPrint("[center] SaveSingleCharacterCamp...can not find character offline data...nCharID:%lu ", nCharID);
		return;
	}

	CharacterCampDBSetRequest req;
	CharacterCampDBData *protoSave = req.add_data();
	if (nullptr == protoSave)
	{
		LogErrFmtPrint("[center] SaveSingleCharacterCamp...can not find character offline data...nCharID:%lu ", nCharID);
		return;
	}

	pCharCamp->SaveData(protoSave);

	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_CAMP, DBPROXY_PROTOCOL_CAMP_PLAYER_SAVE_REQ, &req))
	{
		LogErrFmtPrint("[center] SaveSingleCharacterCamp... SendDataToDBProxy failed...campid:%d,charid:%lu,len:%d ", pOffline->GetCampID(), nCharID,req.ByteSize());
	}
}

void CampMgr::OnDBLoadCampMirrorCallBack(RECV_PACKAGE &package)
{
	AreanLoadMirrorDataCallBack callBack;
	if (!callBack.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[center] CampMgr::OnDBLoadCampMirrorCallBack AreanLoadMirrorDataCallBack parse failed...");
		return;
	}

	CharIDType charId = callBack.charid();
	CharIDType dstId = callBack.dstid();

	OnCampLeaderChall(charId, dstId);
}

//保存离线玩家阵营数据
/*
void CampMgr::SaveOfflineCharCampReq(OfflineCharacterData *pOffline)
{
	if (nullptr == pOffline)	return;

	CharacterCampDBSetRequest req;
	CharacterCampDBData *protoSave = req.add_data();
	if (nullptr == protoSave)	return;

	protoSave->set_charid(pOffline->GetCharID());
	CharacterCampDBOfflineData *offlineData = protoSave->mutable_offline_data();
	if (nullptr == offlineData)	return;

	offlineData->set_official(pOffline->GetOfficial());
	offlineData->set_contribute(pOffline->GetContribute());
	offlineData->set_contri_coin(pOffline->GetContriCoin());

	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_CAMP, DBPROXY_PROTOCOL_CAMP_PLAYER_SAVE_REQ, &req))
	{
		LogErrFmtPrint("[center] SaveSingleCharacterCamp... SendDataToDBProxy failed...campid:%d,charid:%lu ", pOffline->GetCampID(), pOffline->GetCharID());
	}
}*/

//请求保存阵营数据
bool CampMgr::SaveCampDataReq(bool close)
{
	if (!close && !m_bCampNeedSave)
	{
		return true;
	}
	GlobalDBSetRequest req;
	req.set_type_id(EGlobalType_Camp);

	AllCampDBData allproto;
	VecAllCamp::iterator iter = m_vecAllCamp.begin();
	for (; iter != m_vecAllCamp.end(); ++iter)
	{
		Camp *pCamp = (*iter);
		if (nullptr == pCamp)
		{
			continue;
		}
		CampCandidateVec *pElectionRank = pCamp->GetElectionRank();
		CampGodsInfoMap *pGodsInfoMap = pCamp->GetGodsInfo();
		MAP_UINT64_UINT32 &allOfficialMap = pCamp->GetOfficialMap();
		
		SingleCampDBData *protoSingle = allproto.add_all_camp_data();
		if (nullptr != protoSingle)
		{
			protoSingle->set_camp_id(pCamp->CampID());
			protoSingle->set_last_fresh(pCamp->LastFresh());
			protoSingle->set_last_notice(pCamp->LastNotice());
			protoSingle->set_notice(pCamp->Notice());
			protoSingle->set_leader_id(pCamp->LeaderID());

			CampElectionRankDBData *protoElection = protoSingle->mutable_election_rank();
			if (nullptr != pElectionRank && nullptr != protoElection)
			{
				for (CampCandidateVec::iterator iter = pElectionRank->begin(); iter != pElectionRank->end(); ++iter)
				{
					SCampCandidateInfo &cInfo = *iter;
					CampElectionRankInfo *protoRank = protoElection->add_rank();
					if (nullptr != protoRank)
					{
						protoRank->set_char_id(cInfo.nCharId);
						protoRank->set_name(cInfo.szName);
						protoRank->set_level(cInfo.nLevel);
						protoRank->set_prof(cInfo.prof);
						protoRank->set_sex(cInfo.sex);
						protoRank->set_votes(cInfo.votes);
						protoRank->set_votes_gain(cInfo.votesGain);
						protoRank->set_declare(cInfo.declare);
						protoRank->set_num(cInfo.num);
						protoRank->set_lastvotetick(cInfo.lastVoteTick);
					}
				}
			}

			CampGodsInfoDBData *gods_info = protoSingle->mutable_gods_info();
			if (nullptr != pGodsInfoMap && nullptr != gods_info)
			{
				for (CampGodsInfoMap::iterator iter = pGodsInfoMap->begin(); iter != pGodsInfoMap->end(); ++iter)
				{
					SCampGodsInfo &info = iter->second;
					CampGodsInfo *cInfo = gods_info->add_info();
					if (nullptr != gods_info)
					{
						cInfo->set_gods_id(iter->first);
						cInfo->set_num(info.num);
					}
				}
			}

			CampOfficialInfoDBData *official_info = protoSingle->mutable_official_info();
			if (nullptr != official_info)
			{
				for (auto iter = allOfficialMap.begin(); iter != allOfficialMap.end(); ++iter)
				{
					CampOfficialInfo *cInfo = official_info->add_info();
					if (nullptr != cInfo)
					{
						cInfo->set_charid(iter->first);
						cInfo->set_official(iter->second);
					}
				}
			}
		} // end of  if (nullptr != protoSingle)
	}

	allproto.set_last_save_time(g_GetGlobalServerTime()->UnixSec());
	string strCamp = allproto.SerializeAsString();
	req.set_data(strCamp);

	if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_SERV_SYS, DBPROXY_PROTOCOL_GLOBAL_SAVE_REQ, &req))
	{
		LogErrFmtPrint("[center] SaveCampDataReq.....SendDataToDBProxy faild...");
		return false;
	}	
	m_bCampNeedSave = false;

	return true;
}

bool CampMgr::IsLeader(CharIDType nCharID)
{
	OfflineCharacterData *pOff = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(nCharID);
	if (nullptr == pOff)	return false;
	Camp *pCamp = GetCamp(pOff->GetCampID());
	if (nullptr == pCamp)	return false;
	return pCamp->LeaderID() == nCharID;
}

//添加阵营成员
bool CampMgr::AddCampMember(int8_t byCampID, CharIDType nCharID)
{
	Camp *pCamp = GetCamp(byCampID);
	if (nullptr == pCamp)
	{
		return false;
	}

	SET_UINT64 *pMem = pCamp->Chars();
	if (nullptr != pMem)
	{
		pMem->insert(nCharID);
	}

	return true;
}

CharacterCamp *CampMgr::MakeCharacterCampObj()
{
	if (nullptr == m_pCharacterCampPool)
	{
		return nullptr;
	}
	return m_pCharacterCampPool->MallocObj();
}

bool CampMgr::FreeCharacterCampObj(CharacterCamp *pObj)
{
	if (nullptr == pObj)
	{
		return false;
	}
	return m_pCharacterCampPool->FreeObj(pObj);
}

Camp *CampMgr::GetCamp(int8_t byCampID)
{
	if (byCampID > 0 && byCampID < (int8_t)m_vecAllCamp.size())
	{
		return m_vecAllCamp[byCampID];
	}
	return nullptr;
}

CharacterCamp *CampMgr::GetCharacterCamp(CharIDType nCharID)
{
	MapAllCharacterCamp::iterator iter = m_mapAllCharacterCamp.find(nCharID);
	return (iter != m_mapAllCharacterCamp.end()) ? iter->second : nullptr;
}

void CampMgr::UpdateContrib(Camp *pCamp)
{
	if (nullptr == pCamp)			return;
	SET_UINT64 *pMem = pCamp->Chars();
	if (nullptr == pMem)			return;

	VEC_CAMP_RANK vecCampRank;
	vecCampRank.clear();
	SET_UINT64::iterator iterMem = pMem->begin();
	for (; iterMem != pMem->end(); ++iterMem)
	{
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter((*iterMem));
		if (nullptr == pOffline)	continue;
		vecCampRank.push_back(pOffline);
	}
	if (vecCampRank.size() <= 0)	return;
	//根据军功值排序(军功值相等，排名相等)
	std::sort(std::begin(vecCampRank), std::end(vecCampRank), CampMgr::CampSort_ContriFunc);

	MAP_UINT64_UINT32 &officailMap = pCamp->GetOfficialMap();
 	officailMap.clear();

	VEC_CAMP_RANK::iterator it = vecCampRank.begin();
	int32_t rank = 1;
	uint32_t tempContri = (*it)->GetContribute();
	for (; it != vecCampRank.end(); ++it)
	{
		if ((*it)->GetContribute() <= 0)
		{
			DistriOfficial(*it, -1);
			continue;
		}
		if ((*it)->GetContribute() != tempContri)
		{
			++rank;
			tempContri = (*it)->GetContribute();
		}

		//根据军功值匹配的官职加到官职表 在线的即时同步到逻辑服
		DistriOfficial(*it, rank);
	}
}

void CampMgr::DistriOfficial(OfflineCharacterData *pOffline, int32_t rank/*, uint32_t &officialId*/)
{
	if (nullptr == pOffline)
		return;

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
		return;

	const CampOfficialCfgMap *cMap = g_GetCampOfficialCfgTable()->GetCampOfficialCfgMap();
	if (cMap == nullptr)
		return;

	uint32_t officialId = 0;
	for (CampOfficialCfgMap::const_iterator iter = cMap->begin(); iter != cMap->end(); ++iter)
	{
		const CampOfficialCfgInfo &cfg = iter->second;
		if (pCamp->ConfigID() == (uint32_t)cfg.campPartition && ((rank >= cfg.highestOfficialRank && rank <= cfg.lowestOfficialRank) || (cfg.lowestOfficialRank == -1 && rank == -1)))
		{
			officialId = cfg.officialId;
			break;
		}
	}

	if (officialId <= 0)
	{
		LogErrFmtPrint("[center] DistriOfficial.....officialId <= 0.. faild...officialId:%d", officialId);
		return;
	}

	pOffline->SetOfficial(officialId);

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(pOffline->GetCharID());
	if (nullptr != pOnline)
	{
		CenterToLogic_CampCharInfo notify;
		notify.set_charid(pOffline->GetCharID());
		notify.add_attr_id(C_OFFICIAL);
		notify.add_attr_value(pOffline->GetOfficial());
		if (!g_GetCenterService()->SendDataToLogicByCharID(pOffline->GetCharID(), EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify))
		{
			LogErrFmtPrint("[center] CampMgr::DistriOfficial...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", pOffline->GetCampID(), pOffline->GetCharID());
		}
	}
	else
	{
		pCamp->GetOfficialMap()[pOffline->GetCharID()] = officialId;
	}
}

void CampMgr::LogicChangeCamp(CharIDType charID)
{
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pOnline)
	{
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
	if (nullptr == pOffline)
	{
		return;
	}

	CharacterCamp *pCharCamp = GetCharacterCamp(charID);
	if (nullptr == pCharCamp)
	{
		LogErrFmtPrint("[center] CampMgr::LogicChangeCamp ...nullptr == LogicChangeCamp ... charid:%lu ", charID);
		return;
	}

	int8_t byCampID = pOffline->GetCampID();
	if (byCampID != ECamp_Type_Light && byCampID != ECamp_Type_Dark)
	{
		LogErrFmtPrint("[center] CampMgr::LogicChangeCamp ...byCampID != ECamp_Type_Light && byCampID != ECamp_Type_Dark..byCampID:%d", byCampID);
		return;
	}
	Camp *pCamp = GetCamp(byCampID);
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] CampMgr::LogicChangeCamp ...nullptr == pCamp ... charid:%lu,bycampid:%d  ", charID, byCampID);
		return;
	}

	CampProtoInfo protoInfo;
	OfflineCharacterData *pLeaderOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pCamp->LeaderID());
	protoInfo.set_camp_id((int32_t)pCamp->CampID());
	protoInfo.set_notice(pCamp->Notice());
	protoInfo.set_camp_change(1);
	protoInfo.set_dividend_flag(pCharCamp->DividendFlag());
	protoInfo.set_change_camp_tick(pCharCamp->ChangeTick());
	if (nullptr != pLeaderOffline)	protoInfo.set_leader_name(pLeaderOffline->GetCharName());
	if (charID == pCamp->LeaderID())
	{
		uint64_t nLast = pCamp->LastNotice();
		uint64_t nCurTime = g_GetGlobalServerTime()->UnixSec();
		uint64_t nInterSec = ((nCurTime - nLast) >= CampNoticeCDTime) ? 0 : (CampNoticeCDTime - (nCurTime - nLast));
		nInterSec += nCurTime;
		protoInfo.set_notice_cd(nInterSec);
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_INFO_CHANGE, &protoInfo);
}

void CampMgr::KillEnemy(CharIDType charID, CharIDType killID)
{
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pOnline)
	{
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
	if (nullptr == pOffline)
	{
		return;
	}
	ActiveCharacter *pKOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(killID);
	if (nullptr == pKOnline)
	{
		return;
	}
	OfflineCharacterData *pKOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(killID);
	if (nullptr == pKOffline)
	{
		return;
	}

	if (pOffline->GetCampID() <= 0 || pKOffline->GetCampID() <= 0 || pOffline->GetCampID() == pKOffline->GetCampID())
	{
		return;
	}

	CharacterCamp *pCharCamp = GetCharacterCamp(charID);
	CharacterCamp *pKCharCamp = GetCharacterCamp(killID);
	if (nullptr == pCharCamp || nullptr == pKCharCamp)
	{
		return;
	}

	//胜者加军功
	pOffline->SetKillCount(pOffline->GetKillCount() + 1);
	CenterToLogic_CampCharInfo pNotify;
	pNotify.set_charid(pOffline->GetCharID());
	pNotify.add_attr_id(C_CAMP_KILLERS);
	pNotify.add_attr_value(pOffline->GetKillCount());
	const CampOfficialCfgInfo *pCfg = g_GetCampOfficialCfgTable()->GetCampOfficialCfgInfo(pOffline->GetOfficial());
	const CampOfficialCfgInfo *pKCfg = g_GetCampOfficialCfgTable()->GetCampOfficialCfgInfo(pKOffline->GetOfficial());
	if (pCfg && pKCfg && !pCharCamp->IsExist(killID))
	{
		//每日军功获得超过上限则不再增加
		if (pCharCamp->TotalContribute() < (uint32_t)pCfg->medalsLimit)
		{
			pOffline->SetContribute(pOffline->GetContribute() + pKCfg->getMedals);
			pCharCamp->TotalContribute(pCharCamp->TotalContribute() + pKCfg->getMedals);
		}
		pCharCamp->InsertKiller(killID);
		pNotify.add_attr_id(C_CAMP_SCORE);
		pNotify.add_attr_value(pOffline->GetContribute());
	}
	if (!g_GetCenterService()->SendDataToLogicByCharID(pOnline->GetCharID(), EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &pNotify))
	{
		LogErrFmtPrint("[center] CampMgr::KillEnemy...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", pOffline->GetCampID(), pOffline->GetCharID());
	}

	//负者减军功
	if (pKCfg)
	{
		pKOffline->SetContribute(pKOffline->GetContribute() >= (uint32_t)pKCfg->lostMedals ? (pKOffline->GetContribute() - (uint32_t)pKCfg->lostMedals) : 0);

		CenterToLogic_CampCharInfo kNotify;
		kNotify.set_charid(pKOffline->GetCharID());
		kNotify.add_attr_id(C_CAMP_SCORE);
		kNotify.add_attr_value(pKOffline->GetContribute());
		if (!g_GetCenterService()->SendDataToLogicByCharID(pKOnline->GetCharID(), EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &kNotify))
		{
			LogErrFmtPrint("[center] CampMgr::KillEnemy...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", pKOffline->GetCampID(), pKOffline->GetCharID());
		}
	}
}

void CampMgr::Update(uint64_t tick)
{
	_UNUSE(tick);
	uint64_t currTime = ServerTime::UnixSec();
	if (currTime >= (m_lastSaveTime + 60))
	{
		CheckElection();
		SaveCampDataReq();
		m_lastSaveTime = currTime;
	}
	else if (m_bCampNeedSave)
	{
		SaveCampDataReq();
		m_lastSaveTime = currTime;
	}
}

void CampMgr::DailyUpdate()
{
	//刷新阵营总战力、阵营活跃人数
	VecAllCamp::iterator iter = m_vecAllCamp.begin();
	for (; iter != m_vecAllCamp.end(); ++iter)
	{
		Camp *pCamp = (*iter);
		if (nullptr == pCamp)	continue;
		SET_UINT64 *pActiveMem = pCamp->ActiveChars();
		if (nullptr == pActiveMem)	continue;
		pActiveMem->clear();

		//update主神基础祝福
		pCamp->UpdateGods();
	}

	MapAllCharacterCamp::iterator it = m_mapAllCharacterCamp.begin();
	for (; it != m_mapAllCharacterCamp.end(); ++it)
	{
		CharacterCamp *charCamp = it->second;
		if (nullptr == charCamp)	continue;
		FirstLoginDay(charCamp->CharID());
		charCamp->LastLogout(g_GetGlobalServerTime()->UnixSec());
	}
}

void CampMgr::FirstLoginDay(CharIDType charID)
{
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
	if (nullptr == pOffline)	return;

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pOnline)		return;

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)		return;

	CharacterCamp *charCamp = GetCharacterCamp(charID);
	if (nullptr != charCamp)
	{
		charCamp->ResetDay();
		m_setCharacterCampNeedSave.insert(charID);
		charCamp->NeedSave(true);
		//虔诚度衰减
		CampPrayInfoMap &prayMap = charCamp->GetPrayMap();
		for (CampPrayInfoMap::iterator ib = prayMap.begin(), ie = prayMap.end(); ib != ie; ++ib)
		{
			SCampPrayInfo &prayInfo = ib->second;
			uint32_t curDevout = prayInfo.devout;
			uint32_t decDevout = Random(CAMP_PRAY_MIN_DEC_DEVOUT, CAMP_PRAY_MAX_DEC_DEVOUT);
			curDevout = (curDevout >= decDevout) ? (curDevout - decDevout) : 0;
			prayInfo.devout = curDevout;
		}
		//如果角色在线 更新朝拜信息
		Camp_PrayInfoNotify notify;
		notify.set_gods_id(charCamp->GodsID());
		for (CampPrayInfoMap::iterator ib = prayMap.begin(), ie = prayMap.end(); ib != ie; ++ib)
		{
			SCampPrayInfo &prayInfo = ib->second;
			CampProtoPrayInfo *pPrayProto = notify.add_pray_info();
			pPrayProto->set_godid(ib->first);
			pPrayProto->set_devout(prayInfo.devout);
		}
		g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY_CHANGE, &notify);
	}
}

void CampMgr::WeekUpdate()
{
	VecAllCamp::iterator iter = m_vecAllCamp.begin();
	for (; iter != m_vecAllCamp.end(); ++iter)
	{
		Camp *pCamp = (*iter);
		if (nullptr == pCamp)		continue;
		UpdateContrib(pCamp);
	}

	MapAllCharacterCamp::iterator it = m_mapAllCharacterCamp.begin();
	for (; it != m_mapAllCharacterCamp.end(); ++it)
	{
		CharacterCamp *charCamp = it->second;
		if (nullptr == charCamp)	continue;
		FirstLoginWeek(charCamp->CharID(), false);
	}
}

void CampMgr::FirstLoginWeek(CharIDType charID, bool login)
{
	if (login)					return;

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
	if (nullptr == pOffline)	return;

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pOnline)		return;

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)		return;

	CharacterCamp *charCamp = GetCharacterCamp(charID);
	if (nullptr == charCamp)	return;

	charCamp->DividendFlag(false);
	charCamp->DividendTime(g_GetGlobalServerTime()->UnixSec());
	charCamp->LastLogout(g_GetGlobalServerTime()->UnixSec());

	m_setCharacterCampNeedSave.insert(charID);
	charCamp->NeedSave(true);

	CampProtoInfo protoInfo;
	OfflineCharacterData *pLeaderOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pCamp->LeaderID());
	protoInfo.set_camp_id((int32_t)pCamp->CampID());
	protoInfo.set_notice(pCamp->Notice());
	protoInfo.set_camp_change(0);
	protoInfo.set_dividend_flag(charCamp->DividendFlag());
	protoInfo.set_change_camp_tick(charCamp->ChangeTick());
	if (nullptr != pLeaderOffline)	protoInfo.set_leader_name(pLeaderOffline->GetCharName());
	if (charID == pCamp->LeaderID())
	{
		uint64_t nLast = pCamp->LastNotice();
		uint64_t nCurTime = g_GetGlobalServerTime()->UnixSec();
		uint64_t nInterSec = ((nCurTime - nLast) >= CampNoticeCDTime) ? 0 : (CampNoticeCDTime - (nCurTime - nLast));
		nInterSec += nCurTime;
		protoInfo.set_notice_cd(nInterSec);
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_INFO_CHANGE, &protoInfo);

	//军功值超过100点的部分被系统兑换成军功币
	if (pOffline->GetContribute() >= CAMP_CONTRI_COIN)
	{
		pOffline->SetContriCoin(pOffline->GetContriCoin() + pOffline->GetContribute() - CAMP_CONTRI_COIN);
		pOffline->SetContribute(CAMP_CONTRI_COIN);
		CenterToLogic_CampCharInfo c2l_notify;
		c2l_notify.set_charid(charID);
		c2l_notify.add_attr_id(C_CAMP_COIN);
		c2l_notify.add_attr_value(pOffline->GetContriCoin());
		c2l_notify.add_attr_id(C_CAMP_SCORE);
		c2l_notify.add_attr_value(CAMP_CONTRI_COIN);
		g_GetCenterService()->SendDataToLogicByCharID(charID, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &c2l_notify);
	}
}

void CampMgr::ElectionOver(Camp *pCamp)
{
	if (nullptr == pCamp)
		return;

	CampCandidateVec *candiVec = pCamp->GetElectionRank();
	if (nullptr == candiVec || candiVec->size() <= 0)
	{
		pCamp->LeaderID(0);
		UpdateCampLeaderToLogic(pCamp->CampID());
		return;
	}
	SCampCandidateInfo &info = *(candiVec->begin());
	pCamp->LeaderID(info.nCharId);
	UpdateCampLeaderToLogic(pCamp->CampID(), info.nCharId);
	//竞选剩余资金返还
	for (CampCandidateVec::iterator iter = candiVec->begin(); iter != candiVec->end(); iter++)
	{
		SCampCandidateInfo &cInfo = *iter;
		if (cInfo.votes >= cInfo.num)
			continue;
		uint32_t returnMoney = (cInfo.num - cInfo.votes) * cInfo.votesGain;
		if (returnMoney <= 0)
			continue;

		string strTopic = "阵营竞选剩余基金";
		string strContent = "阵营竞选已经结束，多余的投票基金已退回，祝你好运！";
		std::vector<ItemProtoInfo> v;
		g_GetMailMgr()->SendSystemMail(cInfo.nCharId, strTopic, strContent, returnMoney, 0, 0, 0, 0, v);
	}

	SystemChatMsgData msgData;
	msgData.Clear();
	SET_UINT64 *iSet = pCamp->Chars();
	if (nullptr != iSet)
	{
		CharacterPlayerMiniInfo charInfo;
		g_GetChatCenter()->InitPlayerMiniInfoStruct(info.nCharId, charInfo);
		msgData.players.push_back(charInfo);
		msgData.text.push_back(pCamp->CampID() == 1 ? "光之子" : "暗之子");
		msgData.params.push_back(pCamp->CampID());
		g_GetChatCenter()->SendBroadcastChat(BT_FRIEND_CAMP_ELECTION_SUCCESS, msgData, *iSet);
	}

	candiVec->clear();
	m_bCampNeedSave = true;
}

void CampMgr::DuplicatePass(CharIDType charID)
{
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pOnline)
	{
		return;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
	if (nullptr == pOffline)
	{
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charID);
	if (nullptr == charCamp)
	{
		return;
	}

	//副本队伍有等级低于自身10级以上的同阵营玩家时，每通关一次副本增加1点声望，可叠加（即队伍中有多个玩家低于自身10级以上时，每个玩家都会触发声望获取）；
	Team *team = g_GetTeamMgr()->FindTeam(charID);
	if (nullptr == team)
	{
		return;
	}
	TeamMember *memberList = team->GetMemberList();
	if (nullptr == memberList)
	{
		return;
	}
	bool notifyChange = false;
	uint32_t mCount = team->MemberCount();
	for (uint32_t i = 0; i < mCount; i++)
	{
		CharIDType playerId = memberList[i].playerId;
		OfflineCharacterData *pMemOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(playerId);
		if (nullptr == pMemOffline || pOffline->GetCampID() != pMemOffline->GetCampID() || (pOffline->GetLevel() - pMemOffline->GetLevel()) < 10)
		{
			continue;
		}
		pOffline->SetPrestige(pOffline->GetPrestige() + 1);
		pOffline->SetHisPrestige(pOffline->GetHisPrestige() + 1);
		notifyChange = true;
	}

	if (!notifyChange)
	{
		return;
	}

	CenterToLogic_CampCharInfo notify;
	notify.set_charid(charID);
	notify.add_attr_id(C_CAMP_PRESTIGE);
	notify.add_attr_value(pOffline->GetPrestige());
	notify.add_attr_id(C_CAMP_HIS_PRESTIGE);
	notify.add_attr_value(pOffline->GetHisPrestige());
	if (!g_GetCenterService()->SendDataToLogicByCharID(charID, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify))
	{
		LogErrFmtPrint("[center] CampMgr::ChangeCamp...SendDataToLogic failed.. byCampID:%d,charid:%lu ", pOffline->GetCampID(), charID);
	}
}

void CampMgr::GetCampRank(std::vector<RankingListKillPoingData> &vec, int32_t maxCount, enRankingListType type)
{
	ECamp_Type campType = (type == enRankingListType_LightKillPoint) ? ECamp_Type_Light : (type == enRankingListType_BlackKillPoint ? ECamp_Type_Dark : ECamp_Type_None);

	uint8_t attrType = 1;	//1 --contribute, 2 --prestige
	switch (type)
	{
	case enRankingListType_AllKillPoint:
		campType = ECamp_Type_None;
		break;
	case enRankingListType_LightKillPoint:
		campType = ECamp_Type_Light;
		break;
	case enRankingListType_BlackKillPoint:
		campType = ECamp_Type_Dark;
		break;
	case enRankingListType_AllPrestige:
		campType = ECamp_Type_None;
		attrType = 2;
		break;
	case enRankingListType_LightPrestige:
		campType = ECamp_Type_Light;
		attrType = 2;
		break;
	case enRankingListType_BlackPrestige:
		campType = ECamp_Type_Dark;
		attrType = 2;
		break;
	default:
		break;
	}

	SET_UINT64 pMem = GetMems(campType);
	for (auto iter = pMem.begin(); iter != pMem.end(); ++iter)
	{
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter((*iter));
		if (nullptr != pOffline)
		{
			RankingListKillPoingData rData;
			rData.set_cid(pOffline->GetCharID());
			rData.set_username(pOffline->GetCharName());
			rData.set_prof(pOffline->GetProf());
			rData.set_camp(pOffline->GetCampID());
			if (attrType == 1)
			{
				/*if (pOffline->GetKillCount() <= 0)
					continue;
				rData.set_point(pOffline->GetKillCount());*/
				if (pOffline->GetContribute() <= 0)
					continue;
				rData.set_point(pOffline->GetContribute());
			}
			else if (attrType == 2)
			{
				if (pOffline->GetHisPrestige() <= 0)
					continue;
				rData.set_point(pOffline->GetHisPrestige());
			}
			vec.push_back(rData);
		}
	}
	std::sort(std::begin(vec), std::end(vec), CampMgr::CampSort_KillerFunc);
	if (vec.size() > (size_t)maxCount)
	{
		vec.erase(vec.begin() + maxCount, vec.end());
	}
}

void CampMgr::GetPlayerCampInfo(uint64_t cid, enRankingListType type, RankingListKillPoingData &data)
{
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(cid);
	if (nullptr == pOffline)
	{
		return;
	}
	data.set_cid(cid);
	data.set_username(pOffline->GetCharName());
	data.set_prof(pOffline->GetProf());
	data.set_point(0);
	data.set_camp(pOffline->GetCampID());
	switch (type)
	{
	case ProtoBuf::enRankingListType_AllKillPoint:
		data.set_point(pOffline->GetContribute());
		break;
	case ProtoBuf::enRankingListType_LightKillPoint:
		data.set_point(pOffline->GetContribute());
		break;
	case ProtoBuf::enRankingListType_BlackKillPoint:
		data.set_point(pOffline->GetContribute());
		break;
	case ProtoBuf::enRankingListType_AllPrestige:
		data.set_point(pOffline->GetHisPrestige());
		break;
	case ProtoBuf::enRankingListType_LightPrestige:
		data.set_point(pOffline->GetHisPrestige());
		break;
	case ProtoBuf::enRankingListType_BlackPrestige:
		data.set_point(pOffline->GetHisPrestige());
		break;
	default:
		break;
	}
	
}

void CampMgr::UpdateCampLeaderToLogic(int8_t byCampID, CharIDType charId)
{
	Camp *pCamp = GetCamp(byCampID);
	if (nullptr == pCamp)	return;

	const CampFree_choiceCfgInfo *info = g_GetCampFree_choiceCfgTable()->GetCampFree_choiceCfgInfo(pCamp->ConfigID());
	if (nullptr == info)		return;

	if (charId > 0 && charId != pCamp->LeaderID())		return;	//非首领

	bool isplayer = false;
	if (charId <= 0 && pCamp->LeaderID() > 0)
		isplayer = true;
	if (charId > 0 && charId == pCamp->LeaderID())
		isplayer = true;

	CenterToLogic_CampLeader campLeader;
	campLeader.set_camp(byCampID);
	campLeader.set_npc_id(info->campNpcId);
	if (isplayer)
	{
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pCamp->LeaderID());
		if (nullptr == pOffline)	return;
		CharOutward *outWard = campLeader.mutable_out_ward();
		outWard->set_prof(pOffline->GetProf());
		outWard->set_sex(pOffline->GetSex());
		outWard->set_dstname(pOffline->GetCharName());
		CharFacadeProto *proto = outWard->mutable_facade();
		proto->CopyFrom(pOffline->GetFacade());
	}
	g_GetCenterService()->SendDataToLogic(g_GetCenterSceneMgr()->GetLogicIdByMapId(info->mapId), EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHANGE_CAMP_LEADER, &campLeader);
}

void CampMgr::CampSet(CharIDType charid, uint32_t attrid, uint32_t value)
{
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charid);
	if (nullptr == pOnline)
	{
		LogErrFmtPrint("[center] CampMgr::CampSet...ActiveCharacter=nullptr failed.. charid:%lu ", charid);
		return;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charid);
	if (nullptr == pOffline)
	{
		LogErrFmtPrint("[center] CampMgr::CampSet...OfflineCharacterData=nullptr failed.. charid:%lu ", charid);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] CampMgr::CampSet...pCamp=nullptr failed.. campid:%lu ", pOffline->GetCampID());
		return;
	}

	switch (attrid)
	{
	case C_CAMP_SCORE:
		pOffline->SetContribute(value);
		break;
	case C_CAMP_COIN:
		pOffline->SetContriCoin(value);
		break;
	case C_CAMP_PRESTIGE:
		pOffline->SetPrestige(value);
		break;
	case C_CAMP_HIS_PRESTIGE:
		pOffline->SetHisPrestige(pOffline->GetHisPrestige() + value);
		break;
	case C_OFFICIAL:
		{
			const CampOfficialCfgInfo *pCfg = g_GetCampOfficialCfgTable()->GetCampOfficialCfgInfo(value);
			if (nullptr == pCfg || (int32_t)pCamp->ConfigID() != pCfg->campPartition)
				return;
			pOffline->SetOfficial(value);
		}
		break;
	case C_KNIGHT:
		{
			const CampKnighthoodCfgInfo *pCfg = g_GetCampKnighthoodCfgTable()->GetCampKnighthoodCfgInfo(value);
			if (nullptr == pCfg || (int32_t)pCamp->ConfigID() != pCfg->campPartition)
					return;
			pOffline->SetKnight(value);
		}
		break;
	case C_CAMP_KILLERS:
		pOffline->SetKillCount(value);
		break;
/*
	case C_CHARM:	//魅力值
		pOffline->SetCharm(value);
		break;*/
	default:
		break;
	}
	//通知逻辑服更新角色阵营信息
	CenterToLogic_CampCharInfo notify;
	notify.set_charid(charid);
	notify.add_attr_id(attrid);
	notify.add_attr_value(value);

	if (!g_GetCenterService()->SendDataToLogicByCharID(charid, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify))
	{
		LogErrFmtPrint("[center] CampMgr::CampSet...SendDataToLogicByCharID failed.. charid:%lu ", charid);
	}
}

void CampMgr::SetCampLeader(CharIDType leadId)
{
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(leadId);
	if (nullptr == pOnline)
	{
		LogErrFmtPrint("[center] CampMgr::SetCampLeader...ActiveCharacter=nullptr failed.. leadId:%lu ", leadId);
		return;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(leadId);
	if (nullptr == pOffline)
	{
		LogErrFmtPrint("[center] CampMgr::SetCampLeader...OfflineCharacterData=nullptr failed.. leadId:%lu ", leadId);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] CampMgr::SetCampLeader...pCamp=nullptr failed.. campid:%lu ", pOffline->GetCampID());
		return;
	}

	pCamp->LeaderID(leadId);
	UpdateCampLeaderToLogic(pCamp->CampID());
}

void CampMgr::AddCampPrestige(CharIDType charId, uint32_t prestige)
{
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		LogErrFmtPrint("[center] CampMgr::AddCampPrestige...pOffline=nullptr.....charid:%lu ", charId);
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		LogErrFmtPrint("[center] CampMgr::AddCampPrestige...charCamp=nullptr.....charid:%lu ", charId);
		return;
	}

	pOffline->SetPrestige(pOffline->GetPrestige() + prestige);
	pOffline->SetHisPrestige(pOffline->GetHisPrestige() + prestige);
	CenterToLogic_CampCharInfo notify;
	notify.set_charid(charId);
	notify.add_attr_id(C_CAMP_PRESTIGE);
	notify.add_attr_value(pOffline->GetPrestige());
	notify.add_attr_id(C_CAMP_HIS_PRESTIGE);
	notify.add_attr_value(pOffline->GetHisPrestige());
	if (!g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify))
	{
		LogErrFmtPrint("[center] CampMgr::AddCampPrestige...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", pOffline->GetCampID(), pOffline->GetCharID());
	}
}

void CampMgr::CheckOfficial(OfflineCharacterData *pOffline, Camp *pCamp)
{
	if (nullptr == pOffline)	return;
	MAP_UINT64_UINT32 &officailMap = pCamp->GetOfficialMap();
	MAP_UINT64_UINT32::iterator  iter = officailMap.find(pOffline->GetCharID());
	if (iter != officailMap.end())
	{
		pOffline->SetOfficial(iter->second);
		ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(pOffline->GetCharID());
		if (nullptr == pOnline)	
			return;

		CenterToLogic_CampCharInfo notify;
		notify.set_charid(pOffline->GetCharID());
		notify.add_attr_id(C_OFFICIAL);
		notify.add_attr_value(pOffline->GetOfficial());
		if (!g_GetCenterService()->SendDataToLogicByCharID(pOffline->GetCharID(), EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify))
		{
			LogErrFmtPrint("[center] CampMgr::CheckOfficial...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", pOffline->GetCampID(), pOffline->GetCharID());
		}
		officailMap.erase(iter);
	}
}

SET_UINT64 CampMgr::GetMems(ECamp_Type type)
{
	SET_UINT64 iset;
	if (GetCamp(ECamp_Type_Light) == nullptr || GetCamp(ECamp_Type_Dark) == nullptr)
	{
		return iset;
	}
	if (type == ECamp_Type_None)
	{
		SET_UINT64 *pLightMem = GetCamp(ECamp_Type_Light)->Chars();
		SET_UINT64 *pDarkMem = GetCamp(ECamp_Type_Dark)->Chars();
		if (pLightMem == nullptr || pDarkMem == nullptr)
		{
			return iset;
		}
		iset.insert(pDarkMem->begin(), pDarkMem->end());
		iset.insert(pLightMem->begin(), pLightMem->end());
		return iset;
	}
	SET_UINT64 *pSet = GetCamp(type)->Chars();
	iset.insert(pSet->begin(), pSet->end());
	return iset;
}

void CampMgr::CampMemsChange(ECamp_Type type)
{
	if (GetCamp(ECamp_Type_Light) == nullptr || GetCamp(ECamp_Type_Dark) == nullptr)
		return;

	SET_UINT64 *pMem = GetCamp(type)->Chars();
	if (pMem->size() > 100)
		return;

	{
		std::vector<RankingListKillPoingData> vec;
		for (SET_UINT64::iterator iter = pMem->begin(); iter != pMem->end(); ++iter)
		{
			OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter((*iter));
			if (nullptr != pOffline && pOffline->GetKillCount() > 0)
			{
				RankingListKillPoingData rData;
				rData.set_cid(pOffline->GetCharID());
				rData.set_username(pOffline->GetCharName());
				rData.set_prof(pOffline->GetProf());
				rData.set_point(pOffline->GetKillCount());
				vec.push_back(rData);
			}
		}
		std::sort(std::begin(vec), std::end(vec), CampMgr::CampSort_KillerFunc);
		enRankingListType rRank = (type == ECamp_Type_Light) ? enRankingListType_LightKillPoint : enRankingListType_BlackKillPoint;
		g_GetRankingListMgr()->NoticeRefreshKillPoint(vec, rRank);
	}
	{
		SET_UINT64 pAllMem = GetMems(ECamp_Type_None);
		std::vector<RankingListKillPoingData> vec;
		for (SET_UINT64::iterator iter = pAllMem.begin(); iter != pAllMem.end(); ++iter)
		{
			OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter((*iter));
			if (nullptr != pOffline && pOffline->GetKillCount() > 0)
			{
				RankingListKillPoingData rData;
				rData.set_cid(pOffline->GetCharID());
				rData.set_username(pOffline->GetCharName());
				rData.set_prof(pOffline->GetProf());
				rData.set_point(pOffline->GetKillCount());
				vec.push_back(rData);
			}
		}
		std::sort(std::begin(vec), std::end(vec), CampMgr::CampSort_KillerFunc);
		if (vec.size() > 100)
		{
			vec.erase(vec.begin() + 100, vec.end());
		}
		g_GetRankingListMgr()->NoticeRefreshKillPoint(vec, enRankingListType_AllKillPoint);
	}
}

//阵营排序-军功优先
bool CampMgr::CampSort_ContriFunc(OfflineCharacterData *pOfflineA, OfflineCharacterData *pOfflineB)
{
	if (nullptr == pOfflineA || nullptr == pOfflineB)
	{
		return false;
	}
	return pOfflineA->GetContribute() > pOfflineB->GetContribute();
}

//阵营排序-击杀人数优先
bool CampMgr::CampSort_KillerFunc(const RankingListKillPoingData &a, const RankingListKillPoingData &b)
{
	return a.point() > b.point();
}

int8_t CampMgr::CampChoice(int32_t nType, uint32_t &destinyId)
{
	int8_t byCampID = ECamp_Type_None;
	if (1 == nType || 2 == nType)
	{
		byCampID = (int8_t)nType;
		return byCampID;
	}

	Camp *pLightCamp = GetCamp(ECamp_Type_Light);
	Camp *pDarkCamp = GetCamp(ECamp_Type_Dark);

	if (!pLightCamp || !pDarkCamp)
	{
		LogErrFmtPrint("[center] CampMgr::CampChoice.....nullptr = LightCamp || nullptr = DarkCamp faild...");
		return 0;
	}

	uint32_t lightNum = pLightCamp->ActiveNum();
	uint32_t darkNum = pDarkCamp->ActiveNum();
	uint64_t lightFight = 0;
	uint64_t darkFight = 0;

	if (g_GetCenterService()->GetDayCountFromOpen() <= CAMP_RANDOM_CHOICE_OPENDAYS)
	{
		byCampID = (int8_t)Random(1, 2);
	}
	else if (lightNum == 0 && darkNum == 0)
	{
		byCampID = (int8_t)Random(1, 2);
	}
	else
	{
		if (lightNum == darkNum)
		{
			lightFight = pLightCamp->TotalFight();
			darkFight = pDarkCamp->TotalFight();
			if (lightFight == darkFight)
			{
				byCampID = (int8_t)Random(1, 2);
			}
			else if (lightFight > darkFight)
			{
				byCampID = ECamp_Type_Dark;
			}
			else
			{
				byCampID = ECamp_Type_Light;
			}
		}
		else if (lightNum > darkNum)
		{
			byCampID = ECamp_Type_Dark;
		}
		else
		{
			byCampID = ECamp_Type_Light;
		}
	}
	destinyId = CalcDestinyID(lightFight, darkFight);
	return byCampID;
}

uint32_t CampMgr::CalcDestinyID(uint64_t lightFight, uint64_t darkFight)
{
	uint32_t destinyId = 0;
	uint64_t diffFight = lightFight >= darkFight ? (lightFight - darkFight) : (darkFight - lightFight);
	diffFight = diffFight / 500;
	const CampDestiny_choiceCfgMap *cMap = g_GetCampDestiny_choiceCfgTable()->GetCampDestiny_choiceCfgMap();
	if (nullptr != cMap)
	{
		for (CampDestiny_choiceCfgMap::const_iterator iter = cMap->begin(); iter != cMap->end(); ++iter)
		{
			const CampDestiny_choiceCfgInfo &info = iter->second;
			if (diffFight >= (uint64_t)info.dauPowerMin && (info.dauPowerMax == -1 || diffFight <= (uint64_t)info.dauPowerMax))
			{
				destinyId = iter->first;
				break;
			}
		}
	}
	return destinyId;
}

void CampMgr::DoDestinyAwards(ActiveCharacter *pOnline, uint32_t destinyId)
{
	if (destinyId <= 0)		return;
	const CampDestiny_choiceCfgInfo *info = g_GetCampDestiny_choiceCfgTable()->GetCampDestiny_choiceCfgInfo(destinyId);
	if (nullptr == info)	return;
	CenterToLogic_NotifyAddSth addSth;
	addSth.set_char_id(pOnline->GetCharID());
	addSth.set_operate(2);
	uint32_t size = info->vec_destinyRewardId.size();
	for (uint32_t n = 0; n != size; ++n)
	{
		if (info->vec_destinyRewardId[n] > 0)
		{
			addSth.add_item_id(info->vec_destinyRewardId[n]);
			addSth.add_item_num(info->vec_destinyRewardNumber[n]);
		}
	}
	g_GetCenterService()->SendDataToLogicByCharID(pOnline->GetCharID(), EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_TOTIFY_ADD_STH, &addSth);
}

bool CampMgr::IsInEleTime()
{
	Date date;
	Time now = Time::Now();
	now.LocalDate(&date);
	uint32_t nowWeekTick = date.wday * 24 * 60 + date.hour * 60 + date.min;
	if (CampEleCloseTick > CampEleOpenTick)
	{
		if (nowWeekTick >= CampEleOpenTick && nowWeekTick <= CampEleCloseTick)
			return true;
	}
	else
	{
		if (nowWeekTick >= CampEleOpenTick || nowWeekTick <= CampEleCloseTick)
			return true;
	}
	return false;
}

bool CampMgr::IsInVoteTime()
{
	Date date;
	Time now = Time::Now();
	now.LocalDate(&date);
	uint32_t nowWeekTick = date.wday * 24 * 60 + date.hour * 60 + date.min;
	if (CampVoteCloseTick > CampVoteOpenTick)
	{
		if (nowWeekTick >= CampVoteOpenTick && nowWeekTick <= CampVoteCloseTick)
			return true;
	}
	else
	{
		if (nowWeekTick >= CampVoteOpenTick || nowWeekTick <= CampVoteCloseTick)
			return true;
	}
	return false;
}

void CampMgr::CheckElection()
{
	Date date;
	Time now = Time::Now();
	now.LocalDate(&date);
	uint32_t nowWeekTick = date.wday * 24 * 60 + date.hour * 60 + date.min;
	//投票时间结束
	if (nowWeekTick == CampVoteCloseTick)
	{
		VecAllCamp::iterator iter = m_vecAllCamp.begin();
		for (; iter != m_vecAllCamp.end(); ++iter)
		{
			Camp *pCamp = (*iter);
			if (nullptr == pCamp)	continue;
			ElectionOver(pCamp);
		}
	}
}

///////////////////////////////// 客户端 阵营逻辑  /////////////////////////////////////////
//拉取初始数据
void CampMgr::HandClient_CampGetData(CharIDType charId, RECV_PACKAGE &package)
{
	package = package;

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		return;
	}

	Camp_GetDataRsp rsp;
	rsp.set_retcode(RET_SUCCESS);
	CharacterCamp *pCharCamp = GetCharacterCamp(charId);
	if (nullptr == pCharCamp)
	{
		rsp.set_retcode(RET_FAIL);
	}
	else
	{
		rsp.set_gods_id(pCharCamp->GodsID());
		rsp.set_dividend_flag(pCharCamp->DividendFlag());
		rsp.set_challenge(pCharCamp->ChallengeFlag());
		rsp.set_change_camp_tick(pCharCamp->ChangeTick());

		CampPrayInfoMap &prayMap = pCharCamp->GetPrayMap();
		for (CampPrayInfoMap::iterator ib = prayMap.begin(), ie = prayMap.end(); ib != ie; ++ib)
		{
			SCampPrayInfo &prayInfo = ib->second;
			CampProtoPrayInfo *pPrayProto = rsp.add_pray_info();
			pPrayProto->set_godid(ib->first);
			pPrayProto->set_devout(prayInfo.devout);
		}
	}
	if (!g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_GET_DATA, &rsp))
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_CampGetData...SendDataToClient failed.. charid:%lu ", charId);
	}
}

//请求天命选择奖励id
void CampMgr::HandClient_GetDestinyID(CharIDType charId, RECV_PACKAGE &package)
{
	package = package;

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		return;
	}

	Camp *pLightCamp = GetCamp(ECamp_Type_Light);
	Camp *pDarkCamp = GetCamp(ECamp_Type_Dark);

	if (!pLightCamp || !pDarkCamp)
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_GetDestinyID.....nullptr = LightCamp || nullptr = DarkCamp faild...");
		return;
	}

	uint64_t lightFight = pLightCamp->TotalFight();
	uint64_t darkFight = pDarkCamp->TotalFight();
	uint32_t destinyId = CalcDestinyID(lightFight, darkFight);

	Camp_DestinyIdRsp rsp;
	rsp.set_destinyid(destinyId);

	if (!g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_DESTINY, &rsp))
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_GetDestinyID...SendDataToClient failed.. charid:%llu ", charId);
	}
}

//加入阵营
bool CampMgr::HandClient_JoinCamp(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_JoinReq req;
	if (!req.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_JoinReq parse failed...charid:%lu ",charId);
		return false;
	}

	Camp_JoinRsp rsp;
	int32_t nType = req.type();
	if (nType != ECamp_Choice_Type_Light && nType != ECamp_Choice_Type_Dart && nType != ECamp_Choice_Type_Destiny)
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_JoinCamp...Error....type not exist,type:%d", nType);
		rsp.set_retcode(RET_FAIL);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		rsp.set_retcode(RET_PLAYER_NOT_ONLINE);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	if (g_GetTeamMgr()->GetTeamId(charId) > 0)
	{
		rsp.set_retcode(RET_CAMP_CAMP_CHANGE);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_retcode(RET_NOT_HAVE_CHARACTER);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	if (pOffline->GetCampID() > 0)
	{
		rsp.set_retcode(RET_CAMP_ALREADY_IN_CAMP);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	const FunctionunlockFunctionUnlockCfgInfo *pCampOpenLevel = g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_CAMP);
	if (nullptr == pCampOpenLevel)
	{
		rsp.set_retcode(RET_CONFIG_ERROR);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	if (pOffline->GetLevel() < pCampOpenLevel->unlockLevel)
	{
		rsp.set_retcode(RET_LEVEL_LACK);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	CharacterCamp *pCharCamp = GetCharacterCamp(charId);
	if (nullptr != pCharCamp)
	{
		rsp.set_retcode(RET_CAMP_ALREADY_IN_CAMP);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	uint32_t destinyId = 0;
	int8_t byCampID = CampChoice(nType, destinyId);
	Camp *pCamp = GetCamp(byCampID);
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_JoinCamp...nullptr == pCamp.. byCampID:%d ,charid:%lu", byCampID,charId);
		rsp.set_retcode(RET_CAMP_NOT_EXIST);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	const CampFree_choiceCfgInfo *info = g_GetCampFree_choiceCfgTable()->GetCampFree_choiceCfgInfo(pCamp->ConfigID());
	if (nullptr == info)
	{
		LogErrFmtPrint("[center] CampMgr::JoHandClient_JoinCampinCamp...nullptr == CampFree_choiceCfgInfo..configID = %d", pCamp->ConfigID());
		rsp.set_retcode(RET_FAIL);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	SET_UINT64 *pMem = pCamp->Chars();
	if (nullptr == pMem)
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_JoinCamp...nullptr == pMem.. byCampID:%d,charid:%lu ", byCampID, charId);
		rsp.set_retcode(RET_FAIL);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	SET_UINT64 *pActiveMem = pCamp->ActiveChars();
	if (nullptr == pActiveMem)
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_JoinCamp...nullptr == pActiveMem.. byCampID:%d,charid:%lu ", byCampID, charId);
		rsp.set_retcode(RET_FAIL);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}
	
	pCharCamp = MakeCharacterCampObj();
	if (nullptr == pCharCamp)
	{
		LogErrFmtPrint("[center] CampMgr::JoinHandClient_JoinCampCamp...nullptr == pCharCamp.. MakeCharacterCampObj fail...");
		rsp.set_retcode(RET_FAIL);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	//通知逻辑服更新角色阵营信息
	CenterToLogic_CampCharInfo notify;
	notify.set_charid(charId);
	notify.add_attr_id(C_CAMP_ID);
	notify.add_attr_value(byCampID);
	notify.add_attr_id(C_OFFICIAL);
	notify.add_attr_value(info->initialOfficial);
	notify.add_attr_id(C_KNIGHT);
	notify.add_attr_value(info->initiaKnighthood);
	if (!g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify))
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_JoinCamp...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", byCampID, charId);
		rsp.set_retcode(RET_FAIL);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}
	
	CampProtoInfo *protoInfo = rsp.mutable_info();
	if (nullptr == protoInfo)
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_JoinCamp...nullptr = protoInfo...... failed");
		rsp.set_retcode(RET_FAIL);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);
	}

	pMem->insert(charId);
	pActiveMem->insert(charId);
	m_noneCampChars.erase(charId);
	pOffline->ClearCamp();
	pOffline->SetCampID(byCampID);
	pOffline->SetOfficial(info->initialOfficial);
	pOffline->SetKnight(info->initiaKnighthood);
	pCharCamp->Clear();	
	pCharCamp->CharID(charId);
	pCharCamp->LastJoin(0/*g_GetGlobalServerTime()->UnixSec()*/);		//设置加入阵营时间
	pCharCamp->Init(pCamp->ConfigID());
	m_mapAllCharacterCamp[charId] = pCharCamp;
	protoInfo->set_camp_id(byCampID);
	protoInfo->set_notice(pCamp->Notice());

	uint64_t nCurTime = g_GetGlobalServerTime()->UnixSec();
	uint64_t changeTick = nCurTime/* + CampChangeCDTime*/;	//首次进入阵营不需更换CD
	pCharCamp->ChangeTick(changeTick);
	protoInfo->set_change_camp_tick(changeTick);
	OfflineCharacterData *pLeaderOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pCamp->LeaderID());
	if (nullptr != pLeaderOffline)		protoInfo->set_leader_name(pLeaderOffline->GetCharName());
	if (charId == pCamp->LeaderID())
	{
		uint64_t nLast = pCamp->LastNotice();
		uint64_t nInterSec = ((nCurTime - nLast) >= CampNoticeCDTime) ? 0 : (CampNoticeCDTime - (nCurTime - nLast));
		nInterSec += nCurTime;
		protoInfo->set_notice_cd(nInterSec);
	}
	rsp.set_retcode(RET_SUCCESS);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_CAMP, CENTER_TO_CLIENT_CAMP_JOIN, &rsp);

	DoDestinyAwards(pOnline, destinyId);
	CampMemsChange((ECamp_Type)byCampID);

	pCamp->AddChars(pOffline);
	g_GetTeamMgr()->QuitTeam(charId);
	g_GetRelationMgr()->CampChange(pOffline);

	m_setCharacterCampNeedSave.insert(charId);
	pCharCamp->NeedSave(true);

	return true;
}

//阵营信息
void CampMgr::HandClient_CampInfo(CharIDType charId, RECV_PACKAGE &package)
{
	package = package;
	Camp_CampInfoRsp rsp;
	rsp.set_retcode(RET_SUCCESS);

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		rsp.set_retcode(RET_PLAYER_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_INFO, &rsp);
		return;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_retcode(RET_NOT_HAVE_CHARACTER);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_INFO, &rsp);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		rsp.set_retcode(RET_CAMP_NOT_EXIST);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_INFO, &rsp);
		return;
	}

	CharacterCamp *pCharCamp = GetCharacterCamp(charId);
	if (nullptr == pCharCamp)
	{
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_INFO, &rsp);
		return;
	}

	CampProtoInfo *protoInfo = rsp.mutable_info();
	if (nullptr != protoInfo)
	{
		protoInfo->set_camp_id((int32_t)pCamp->CampID());
		protoInfo->set_change_camp_tick(pCharCamp->ChangeTick());
		OfflineCharacterData *pLeaderOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pCamp->LeaderID());
		if (nullptr != pLeaderOffline)
		{
			protoInfo->set_leader_name(pLeaderOffline->GetCharName());
		}		
		protoInfo->set_notice(pCamp->Notice());		
		if (charId == pCamp->LeaderID())
		{
			uint64_t nLast = pCamp->LastNotice();
			uint64_t nCurTime = g_GetGlobalServerTime()->UnixSec();
			uint64_t nInterSec = ((nCurTime - nLast) >= CampNoticeCDTime) ? 0 : (CampNoticeCDTime - (nCurTime - nLast));
			nInterSec += nCurTime;
			protoInfo->set_notice_cd(nInterSec);
		}
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_INFO, &rsp);
}

//阵营排名
void CampMgr::HandClient_CampRank(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_RankInfoReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_RankInfoReq parse failed...charid:%lu ", charId);
		return;
	}

	Camp_RankInfoRsp rsp;
	rsp.set_retcode(RET_FAIL);

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_RANK_INFO, &rsp);
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_RANK_INFO, &rsp);
		return;
	}
	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_RANK_INFO, &rsp);
		return;
	}
	////排名类型： 1-等级，2-战力，3-官阶，4-爵位
	int32_t type = req.rank_type();
	if (type <= ECamp_Sort_Type_None || type >= ECamp_Sort_Type_Limit)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_RANK_INFO, &rsp);
		return;
	}

	VEC_CAMP_RANK *pRank = pCamp->GetRankData((ECamp_Sort_Type)req.rank_type());
	if (nullptr == pRank)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_RANK_INFO, &rsp);
		return;
	}

	rsp.set_retcode(RET_SUCCESS);
	rsp.set_rank_type(req.rank_type());
	for (VEC_CAMP_RANK::iterator ib = pRank->begin(), ie = pRank->end(); ib != ie; ++ib)
	{
		OfflineCharacterData *pOffline = *ib;
		if (nullptr == pOffline)	continue;
		CampProtoRankInfo *protoInfo = rsp.add_info();
		if (nullptr != protoInfo)
		{
			protoInfo->set_charid(pOffline->GetCharID());
			protoInfo->set_name(pOffline->GetCharName());
			protoInfo->set_level(pOffline->GetLevel());
			protoInfo->set_fight(pOffline->GetFight());
			protoInfo->set_official(pOffline->GetOfficial());
			protoInfo->set_knight(pOffline->GetKnight());
		}
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_RANK_INFO, &rsp);
}

//阵营荣誉
void CampMgr::HandClient_CampHonor(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_HonorInfoReq req;
	if (!req.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_HonorInfoReq parse failed...charid:%lu ", charId);
		return;
	}
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		return;
	}
	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		return;
	}
	Camp_HonorInfoRsp rsp;
	rsp.set_retcode(RET_SUCCESS);
	CharacterCamp *pCharCamp = GetCharacterCamp(charId);
	if (nullptr != pCharCamp)
	{
		CampProtoHonorInfo *protoInfo = rsp.mutable_info();
		if (nullptr != protoInfo)
		{
			protoInfo->set_total_contribute(pCharCamp->TotalContribute());
			//protoInfo->set_kill_enemy_camp(pOffline->GetKillCount());
		}
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_HONOR_INFO, &rsp);
}

void CampMgr::HandClient_CampDevidend(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_DividendReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_DividendReq parse failed...charid:%lu ", charId);
		return;
	}
	Camp_DividendRsp rsp;
	rsp.set_retcode(RET_SUCCESS);

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)		return;

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)	return;

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)		return;

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)	return;

	LogDebugFmtPrint("CharacterCamp::HandClient_CampDevidend...charid:%lu, m_nDividendTime:%lu, m_nDividendFlag:%d ", charId, charCamp->DividendTime(), charCamp->DividendFlag());
	if (charCamp->DividendFlag() == true)
	{
		rsp.set_retcode(RET_CAMP_PRAY_DEVIDEND_HAS_GOT);
	}
	else
	{
		charCamp->DividendFlag(true);
		charCamp->DividendTime(g_GetGlobalServerTime()->UnixSec());
		m_setCharacterCampNeedSave.insert(charId);
		charCamp->NeedSave(true);
		LogDebugFmtPrint("CharacterCamp::HandClient_CampDevidend 11...charid:%lu, m_nDividendTime:%lu, m_nDividendFlag:%d ", charId, charCamp->DividendTime(), charCamp->DividendFlag());
		const CampKnighthoodCfgInfo *info = g_GetCampKnighthoodCfgTable()->GetCampKnighthoodCfgInfo(pOffline->GetKnight());
		if (info)
		{
			CenterToLogic_NotifyAddSth addSth;
			addSth.set_char_id(charId);
			addSth.set_operate(3);
			uint32_t size = info->vecCampKnighthoodDividendCfg.size();
			for (uint32_t n = 0; n != size; ++n)
			{
				if (info->vecCampKnighthoodDividendCfg[n].Id > 0)
				{
					addSth.add_item_id(info->vecCampKnighthoodDividendCfg[n].Id);
					addSth.add_item_num(info->vecCampKnighthoodDividendCfg[n].Number);
				}
			}
			g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_TOTIFY_ADD_STH, &addSth);
		}
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_DIVIDEND, &rsp);
}

//发布公告
void CampMgr::HandClient_PublishNotice(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_PublishNoticeReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_PublishNoticeReq parse failed...charid:%lu ", charId);
		return;
	}
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		return;
	}
	int8_t byCampID = pOffline->GetCampID();
	Camp *pCamp = GetCamp(byCampID);
	if (nullptr == pCamp)
	{
		return;
	}
	MAP_INT8_STRING::iterator iter = m_mapWaitCampNotice.find(byCampID);
	if (iter != m_mapWaitCampNotice.end())
	{
		return;
	}

	Camp_PublishNoticeRsp rsp;
	if (pCamp->LeaderID() != charId)
	{
		//只有首领才能发公告 RET_CAMP_LEADER_CAN_PUBLISH_NOTICE
		rsp.set_retcode(RET_CAMP_LEADER_CAN_PUBLISH_NOTICE);
	}
	else if (req.notice().length() >= CAMP_NOTICE_MAX_LEN)
	{
		//公告长度限制 RET_CAMP_NOTICE_LEN_LIMIT
		rsp.set_retcode(RET_CAMP_NOTICE_LEN_LIMIT);
	}
	else
	{
		uint64_t nCurTime = g_GetGlobalServerTime()->UnixSec();
		uint64_t nInterSec = nCurTime - pCamp->LastNotice();
		if (nInterSec < CampNoticeCDTime)
		{
			//公告CD RET_CAMP_NOTICE_CD_LIMIT
			rsp.set_retcode(RET_CAMP_NOTICE_CD_LIMIT);
		}
		else
		{
			CenterToLogic_CheckNoticeCostReq reqLogic;
			reqLogic.set_char_id(charId);
			reqLogic.set_camp_id(byCampID);
			reqLogic.set_diamond(CampPublishNoticeCostDiamd);
			if (g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHECK_NOTICE_COST_REQ, &reqLogic))
			{
				m_mapWaitCampNotice[byCampID] = req.notice();
			}
			else
			{
				LogErrFmtPrint("[center] CampMgr::HandClient_PublishNotice....SendDataToLogicByCharID failed.... ,campd_id:%d, charid:%llu ",byCampID,charId );
			}
			return;
		}
	}

	g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PUBLISH_NOTICE, &rsp);
}

//竞选申请
void CampMgr::HandClient_CampElection(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_ElectionReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_ElectionReq parse failed...charid:%lu ", charId);
		return;
	}

	Camp_ElectionRsp rsp;
	rsp.set_retcode(RET_FAIL);

	//当前版本屏蔽阵营竞选
	//g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
	//return;

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		rsp.set_retcode(RET_CAMP_NOT_EXIST);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}

	if (pCamp->CampID() == ECamp_Type_Light)
	{
		if (pOffline->GetOfficial() > CampElecMinLightOfficial)
		{
			rsp.set_retcode(RET_CAMP_OFFICIAL_LIMIT);
			g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
			return;
		}
		else if (pOffline->GetKnight() < CampElecMinLightKnight)
		{
			rsp.set_retcode(RET_CAMP_KNIGHT_LIMIT);
			g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
			return;
		}
	}
	else if (pCamp->CampID() == ECamp_Type_Dark)
	{
		if (pOffline->GetOfficial() > CampElecMinDarkOfficial)
		{
			rsp.set_retcode(RET_CAMP_OFFICIAL_LIMIT);
			g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
			return;
		}
		else if (pOffline->GetKnight() < CampElecMinDarkKnight)
		{
			rsp.set_retcode(RET_CAMP_KNIGHT_LIMIT);
			g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
			return;
		}
	}
	else
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}

	if (!IsInEleTime())
	{
		rsp.set_retcode(RET_CAMP_ERROR_ELECTIONT_TIME);
	}
	else if (pOffline->GetLevel() < CampElectionMinLevel)
	{
		rsp.set_retcode(RET_LEVEL_LACK);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}
	else if (pOffline->GetPrestige() < CampElectionCostPrestige)
	{
		rsp.set_retcode(RET_CAMP_PRESTIGE_LACK);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}
	else if (pCamp->Election(charId))
	{
		rsp.set_retcode(RET_CAMP_JOIN_ECLETION);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}
	else if (pCamp->LeaderID() > 0 && charCamp->CharID() != pCamp->LeaderID() && !charCamp->ChallengeFlag())
	{
		rsp.set_retcode(RET_CAMP_HAS_NOT_CHALLENGE);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &rsp);
		return;
	}
	else
	{
		//发消息到逻辑服判断金币钻石是否足够
		CenterToLogic_CheckElectionCostReq reqLogic;
		reqLogic.set_char_id(charId);
		reqLogic.set_votes_gain(req.votes_gain());
		reqLogic.set_diamond(CampElectionCostDiamond);
		reqLogic.set_num(req.num());
		reqLogic.set_declare(req.declare());
		if (!g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHECK_ELECTION_COST_REQ, &reqLogic))
		{
			LogErrFmtPrint("[center] CampMgr::HandClient_CampElection....SendDataToLogicByCharID failed... ,campd_id:%d, charid:%lu ", pOffline->GetCampID(), charId);
		}
	}
}

//竞选投票
void CampMgr::HandClient_CampVote(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_VoteReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_VoteReq parse failed...charid:%lu ", charId);
		return;
	}

	Camp_VoteRsp rsp;
	rsp.set_retcode(RET_SUCCESS);

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		rsp.set_retcode(RET_PLAYER_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_retcode(RET_NOT_HAVE_CHARACTER);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		rsp.set_retcode(RET_CAMP_NOT_EXIST);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	if (!IsInVoteTime())
	{
		rsp.set_retcode(RET_CAMP_ERROR_VOTE_TIME);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	if (pOffline->GetLevel() < CAMP_VOTE_MIN_LEVEL)
	{
		rsp.set_retcode(RET_LEVEL_LACK);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	if (pOffline->GetPrestige() < CampVoteCostPrestige)
	{
		rsp.set_retcode(RET_CAMP_PRESTIGE_LACK);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	if (charCamp->VoteFlag())
	{
		rsp.set_retcode(RET_CAMP_HAS_VOTE);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}
	
	SCampCandidateInfo* cInfo = pCamp->GetCandiInfo(req.charid());
	if (nullptr == cInfo)
	{
		rsp.set_retcode(RET_CAMP_CANDIDATE_NOT_EXIST);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	CenterToLogic_CheckVoteReq checkVoteReq;
	checkVoteReq.set_char_id(charId);
	checkVoteReq.set_electioneer_id(req.charid());
	g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHECK_VOTE_REQ, &checkVoteReq);
}

//竞选排名信息
void CampMgr::HandClient_CampElectionRank(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_ElectionRankReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_ElectionRankReq parse failed...charid:%lu ", charId);
		return;
	}

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		return;
	}
	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		return;
	}

	CampCandidateVec *cVec = pCamp->GetElectionRank();
	if (nullptr == cVec)
	{
		return;
	}

	//若本周投票玩家删角
	if (charCamp->VoteFlag())
	{
		CharIDType electioneerId = charCamp->ElectioneerId();
		OfflineCharacterData *pElectioneerOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(electioneerId);
		if (nullptr == pElectioneerOffline)
		{
			charCamp->VoteFlag(false);
			charCamp->ElectioneerId(0);
			m_setCharacterCampNeedSave.insert(charId);
			charCamp->NeedSave(true);
		}
	}

	Camp_ElectionRankRsp rsp;
	rsp.set_charid(charCamp->ElectioneerId());
	for (CampCandidateVec::const_iterator iter = cVec->begin(); iter != cVec->end(); ++iter)
	{
		const SCampCandidateInfo &cInfo = *iter;
		CampElectionRankInfo *protoInfo = rsp.add_info();
		if (nullptr != protoInfo)
		{
			protoInfo->set_char_id(cInfo.nCharId);
			protoInfo->set_name(cInfo.szName);
			protoInfo->set_level(cInfo.nLevel);
			protoInfo->set_prof(cInfo.prof);
			protoInfo->set_sex(cInfo.sex);
			protoInfo->set_votes(cInfo.votes);
			protoInfo->set_votes_gain(cInfo.votesGain);
			protoInfo->set_declare(cInfo.declare);
		}
	}
	
	g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION_INFO, &rsp);
}

//挑战阵营首领
void CampMgr::HandClient_CampChallenge(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_ChallengeRsp rsp;
	rsp.set_retcode(RET_FAIL);
	rsp.set_is_win(false);

	//当前版本屏蔽阵营竞选
	//g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
	//return;

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		LogErrFmtPrint("[center] HandClient_CampChallenge pnullptr == pOnline...charid:%lu ", charId);
		rsp.set_retcode(RET_FAIL);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		LogErrFmtPrint("[center] HandClient_CampChallenge pnullptr == pOffline...charid:%lu ", charId);
		rsp.set_retcode(RET_FAIL);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] HandClient_CampChallenge pnullptr == pCamp...campId:%d ", pOffline->GetCampID());
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		LogErrFmtPrint("[center] HandClient_CampChallenge pnullptr == charCamp...charid:%lu ", charId);
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}
	if (charId == pCamp->LeaderID())
	{
		LogErrFmtPrint("[center] HandClient_CampChallenge charId == pCamp->LeaderID()...charid:%lu ", charId);
		rsp.set_retcode(RET_FAIL);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}

	if (charCamp->ChallengeFlag())
	{
		rsp.set_retcode(RET_FAIL);
		rsp.set_is_win(true);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}

	if (pCamp->LeaderID() > 0)
	{
		return OnCampLeaderChall(charId, pCamp->LeaderID());
	}

	CharacterMirrorData mirrorData;
	mirrorData.set_type(ARENA_CHALLENGE_TYPE_ROBOT);
	if (pCamp->CampID() == ECamp_Type_Light)
		mirrorData.set_charid(CampLightLeaderNpc);
	else
		mirrorData.set_charid(CampDarkLeaderNpc);
	
	ERetCode retCode = (ERetCode)g_GetCenterDuplicateMgr()->enterCampDup(charId, mirrorData);
	if (RET_SUCCESS != retCode)
	{
		rsp.set_retcode(retCode);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
	}
}

//提升爵位
void CampMgr::HandClient_CampKnightUp(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_KnightUpReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_KnightUpReq parse failed...charid:%lu ", charId);
		return;
	}

	Camp_KnightUpRsp rsp;
	rsp.set_retcode(RET_FAIL);

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_KNIGHT_UP, &rsp);
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_KNIGHT_UP, &rsp);
		return;
	}
	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_KNIGHT_UP, &rsp);
		return;
	}
	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_KNIGHT_UP, &rsp);
		return;
	}

	uint32_t curKnight = pOffline->GetKnight();
	const CampKnighthoodCfgInfo *pCfg = g_GetCampKnighthoodCfgTable()->GetCampKnighthoodCfgInfo(++curKnight);
	if (nullptr == pCfg || pCfg->campPartition != (int32_t)pCamp->ConfigID())
	{
		rsp.set_retcode(RET_CAMP_TOP_KNIGHT_NOW);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_KNIGHT_UP, &rsp);
		return;
	}

	if ((int32_t)pOffline->GetPrestige() < pCfg->lowestReputation)
	{
		rsp.set_retcode(RET_CAMP_PRESTIGE_LACK);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_KNIGHT_UP, &rsp);
		return;
	}

	if ((int32_t)pOffline->GetPrestige() < pCfg->reputationSpend)
	{
		rsp.set_retcode(RET_CAMP_PRESTIGE_LACK);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_KNIGHT_UP, &rsp);
		return;
	}

	pOffline->SetKnight(pCfg->knighthoodId);
	pOffline->SetPrestige(pOffline->GetPrestige() - pCfg->reputationSpend);
	CenterToLogic_CampCharInfo notify;
	notify.set_charid(pOffline->GetCharID());
	notify.add_attr_id(C_KNIGHT);
	notify.add_attr_value(pCfg->knighthoodId);
	notify.add_attr_id(C_CAMP_PRESTIGE);
	notify.add_attr_value(pOffline->GetPrestige());
	
	if (!g_GetCenterService()->SendDataToLogicByCharID(pOffline->GetCharID(), EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify))
	{
		LogErrFmtPrint("[center] CampMgr::HandClient_CampKnightUp...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", pOffline->GetCampID(), pOffline->GetCharID());
	}
}

void CampMgr::HandClient_CampChange(CharIDType charId, RECV_PACKAGE &package)
{
	Camp_ChangeReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] Camp_ChangeReq parse failed...charid:%lu ", charId);
		return;
	}

	Camp_ChangeRsp rsp;
	rsp.set_retcode(RET_SUCCESS);

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_retcode(RET_NOT_HAVE_CHARACTER);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		rsp.set_retcode(RET_PLAYER_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}

	//公会会长不能更换
	CUnion *pUnion = g_GetUnionMgr()->GetCharUnion(charId);
	if (pUnion && pUnion->LeaderId() == charId)
	{
		rsp.set_retcode(RET_CAMP_CHANGE_UNION_ERROR);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}

	//组队状态不能更换
	if (g_GetTeamMgr()->GetTeamId(charId) > 0)
	{
		rsp.set_retcode(RET_CAMP_CAMP_CHANGE);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}

	CharacterCamp *pCharCamp = GetCharacterCamp(charId);
	if (nullptr == pCharCamp)
	{
		LogErrFmtPrint("[center] CampMgr::ChangeCamp ...nullptr == pCharCamp ... charid:%lu ", charId);
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}

	int8_t byCampID = pOffline->GetCampID();
	if (byCampID != ECamp_Type_Light && byCampID != ECamp_Type_Dark)
	{
		LogErrFmtPrint("[center] CampMgr::ChangeCamp ...byCampID != ECamp_Type_Light && byCampID != ECamp_Type_Dark..byCampID:%d", byCampID);
		rsp.set_retcode(RET_CONFIG_ERROR);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}
	Camp *pCamp = GetCamp(byCampID);
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] CampMgr::ChangeCamp ...nullptr == pCamp ... charid:%lu,bycampid:%d  ", charId, byCampID);
		rsp.set_retcode(RET_CAMP_NOT_EXIST);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}

	if (pCamp->LeaderID() == charId)
	{
		rsp.set_retcode(RET_CAMP_CHANGE_LEADER_ERROR);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}

	uint64_t nCurSec = g_GetGlobalServerTime()->UnixSec();
	if (nCurSec < pCharCamp->ChangeTick())
	{
		rsp.set_retcode(RET_CAMP_CHANGE_IN_CD);
		g_GetCenterService()->SendDataToClient(charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
		return;
	}

	CenterToLogic_CheckCampChangeReq changeReq;
	changeReq.set_char_id(charId);
	if (!g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHECK_CHANGE_REQ, &changeReq))
	{
		LogErrFmtPrint("[center] CampMgr::ChangeCamp...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", byCampID, charId);
		rsp.set_retcode(RET_FAIL);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
	}
}

void CampMgr::OnCampLeaderChall(CharIDType charId, CharIDType dstId)
{
	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)	return;

	MirrorRole* pMirrorRole = g_GetMirrorMgr()->Get(dstId);
	if (pMirrorRole != nullptr)
	{
		//如果镜像缓存中存在那么直接将数据打包传给副本
		CharacterMirrorData* pMirrorData = pMirrorRole->Get();
		if (pMirrorData != nullptr)
		{
			pMirrorData->set_type(ARENA_CHALLENGE_TYPE_CAMP_LEADER);
			g_GetCenterDuplicateMgr()->enterCampDup(charId, *pMirrorData);
			return;
		}
	}

	//如果没有请求DB加载镜像数据
	ProtoBuf::AreanLoadMirrorDataCallBack callBack;
	callBack.set_charid(charId);
	callBack.set_dstid(dstId);

	//交给系统管理器去负责加载镜像数据
	g_GetMirrorMgr()->LoadCharacterMirrorData(dstId, EMODULE_ID_CAMP, DBPROXY_PROTOCOL_LOAD_CAMP_MIRROR_DATA_CALL_BACK, &callBack);
}

///////////////////////////  逻辑服和中心服之间的消息 ///////////////////////////////////////////////
//逻辑服返回中心服验证公告扣费
void CampMgr::LogicToCenter_CheckNoticeCost(RECV_PACKAGE &package)
{
	LogicToCenter_CheckNoticeCostRsp rsp;
	if (!rsp.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CheckNoticeCostRsp parse failed...");
		return;
	}

	int32_t retcode = rsp.retcode();
	int8_t byCampID = (int8_t)rsp.camp_id();
	CharIDType charID = rsp.char_id();

	MAP_INT8_STRING::iterator iterNotice = m_mapWaitCampNotice.find(byCampID);
	if (iterNotice == m_mapWaitCampNotice.end())
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CheckNoticeCost....nullptr == pCamp...campid:%d, charid :%lu ,retcode:%d ", byCampID, charID, retcode);
		return;
	}
	std::string strNotice = iterNotice->second;
	m_mapWaitCampNotice.erase(iterNotice);
	//从等待发送公告中删除
	Camp *pCamp = GetCamp(byCampID);
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CheckNoticeCost....nullptr == pCamp...campid:%d, charid :%lu ,retcode:%d ",byCampID,charID,retcode);
		return;
	}
	if (RET_FAIL != retcode)
	{
		Camp_PublishNoticeRsp rsp;
		if (RET_SUCCESS == retcode)
		{
			//修改公告
			pCamp->Notice(strNotice.c_str());
			//修改发送时间
			pCamp->LastNotice(g_GetGlobalServerTime()->UnixSec());
			rsp.set_notice_cd(pCamp->LastNotice() + CampNoticeCDTime);
			//需要保存阵营信息
			m_bCampNeedSave = true;

			//通知阵营成员新公告
			SET_UINT64 *pMem = pCamp->Chars();
			Camp_BroadNoticeRsp broad;
			broad.set_notice(strNotice);
			g_GetCenterService()->SendDataToClient(*pMem, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_BROAD_NOTICE, &broad);
			//阵营公告跑马灯
			SET_UINT64::iterator iterMem = pMem->begin();
			for (; iterMem != pMem->end(); ++iterMem)
			{
				g_GetChatCenter()->ChatCampRumor((*iterMem), strNotice);

				string strTopic = "阵营公告";
				std::vector<ItemProtoInfo> v;
				g_GetMailMgr()->SendSystemMail((*iterMem), strTopic, strNotice, 0, 0, 0, 0, 0, v);
			}			
		}
		//设置返回码
		rsp.set_retcode(retcode);
		g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PUBLISH_NOTICE, &rsp);
	}
}

//逻辑服返回中心服竞选公告扣费
void CampMgr::LogicToCenter_CheckElectionCost(RECV_PACKAGE &package)
{
	LogicToCenter_CheckElectionCostRsp rsp;
	if (!rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CheckElectionCostRsp parse failed...");
		return;
	}
	int32_t retcode = rsp.retcode();
	CharIDType charID = rsp.char_id();
	uint32_t votesGain = rsp.votes_gain();
	uint32_t num = rsp.num();

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pOnline)
	{
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
	if (nullptr == pOffline)
	{
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		return;
	}
	CharacterCamp *charCamp = GetCharacterCamp(charID);
	if (nullptr == charCamp)
	{
		return;
	}

	Camp_ElectionRsp electionRsp;
	electionRsp.set_retcode(retcode);
	if (RET_SUCCESS == retcode)
	{
		//扣除声望
		pOffline->SetPrestige(pOffline->GetPrestige() >= CampElectionCostPrestige ? (pOffline->GetPrestige() - CampElectionCostPrestige) : 0);
		CenterToLogic_CampCharInfo notify;
		notify.set_charid(charID);
		notify.add_attr_id(C_CAMP_PRESTIGE);
		notify.add_attr_value(pOffline->GetPrestige());
		g_GetCenterService()->SendDataToLogicByCharID(charID, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify);

		//添加到竞选人列表
		SCampCandidateInfo cInfo;
		cInfo.nCharId = charID;
		SafeCopyString(cInfo.szName, sizeof(cInfo.szName), pOffline->GetCharName());
		SafeCopyString(cInfo.declare, sizeof(cInfo.declare), rsp.declare().c_str());
		cInfo.prof = pOffline->GetProf();
		cInfo.sex = pOffline->GetSex();
		cInfo.nLevel = pOffline->GetLevel();
		cInfo.votesGain = votesGain;
		cInfo.num = num;
		pCamp->AddCandi(cInfo);
		m_bCampNeedSave = true;
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_ELECTION, &electionRsp);
}

//逻辑服返回中心服验证投票
void CampMgr::LogicToCenter_CheckVote(RECV_PACKAGE &package)
{
	LogicToCenter_CheckVoteRsp checkRsp;
	if (!checkRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CheckVoteRsp parse failed...");
		return;
	}
	int32_t retcode = checkRsp.retcode();
	CharIDType charId = checkRsp.char_id();
	CharIDType nelectioneerID = checkRsp.electioneer_id();

	Camp_VoteRsp rsp;
	rsp.set_retcode(retcode);

	if (RET_SUCCESS != retcode)
	{
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		rsp.set_retcode(RET_PLAYER_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		rsp.set_retcode(RET_NOT_HAVE_CHARACTER);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		rsp.set_retcode(RET_CAMP_NOT_EXIST);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	SCampCandidateInfo* cInfo = pCamp->GetCandiInfo(nelectioneerID);
	if (nullptr == cInfo)
	{
		rsp.set_retcode(RET_CAMP_CANDIDATE_NOT_EXIST);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);
		return;
	}

	charCamp->VoteFlag(true);
	charCamp->ElectioneerId(checkRsp.electioneer_id());
	m_setCharacterCampNeedSave.insert(charId);
	charCamp->NeedSave(true);

	cInfo->votes++;	//需即时排序?
	cInfo->lastVoteTick = g_GetGlobalServerTime()->UnixSec();
	pCamp->ElectionRank();

	pOffline->SetPrestige(pOffline->GetPrestige() >= CampVoteCostPrestige ? (pOffline->GetPrestige() - CampVoteCostPrestige) : 0);
	CenterToLogic_CampCharInfo notify;
	notify.set_charid(charId);
	notify.add_attr_id(C_CAMP_PRESTIGE);
	notify.add_attr_value(pOffline->GetPrestige());
	g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify);

	CampElectionRankInfo *protoInfo = rsp.mutable_info();
	if (nullptr != protoInfo)
	{
		protoInfo->set_char_id(cInfo->nCharId);
		protoInfo->set_name(cInfo->szName);
		protoInfo->set_level(cInfo->nLevel);
		protoInfo->set_prof(cInfo->prof);
		protoInfo->set_sex(cInfo->sex);
		protoInfo->set_votes(cInfo->votes);
		protoInfo->set_votes_gain(cInfo->votesGain);
		protoInfo->set_declare(cInfo->declare);
	}

	//投票获得奖励
	if (cInfo->votes <= cInfo->num)
	{
		CenterToLogic_NotifyAddSth addSth;
		addSth.set_char_id(charId);
		addSth.set_gold(cInfo->votesGain);
		addSth.set_operate(1/*竞选投票*/);
		g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_TOTIFY_ADD_STH, &addSth);
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_VOTE, &rsp);

	m_bCampNeedSave = true;
}

//逻辑服返回中心服验证朝拜扣除道具
void CampMgr::LogicToCenter_CheckPrayCost(RECV_PACKAGE &package)
{
	LogicToCenter_CheckPrayCostRsp rsp;
	if (!rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CheckPrayCost parse failed...");
		return;
	}
	
	int32_t retcode = rsp.retcode();
	CharIDType charID = rsp.char_id();
	uint32_t godId = rsp.gods_id();
	uint32_t godType = rsp.gods_type();

	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pOnline)
	{
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
	if (nullptr == pOffline)
	{
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		return;
	}
	CharacterCamp *charCamp = GetCharacterCamp(charID);
	if (nullptr == charCamp)
	{
		return;
	}

	SCampPrayInfo *pPrayInfo = charCamp->GetPray(godId);
	if (nullptr == pPrayInfo)
	{
		return;
	}

	Camp_PrayRsp prayRsp;
	prayRsp.set_retcode(retcode);

	if (retcode == RET_SUCCESS)
	{
		const CampGodsCfgInfo *pGodCfg = g_GetCampGodsCfgTable()->GetCampGodsCfgInfo(godId);
		if (nullptr == pGodCfg)
		{
			return;
		}
		const CampFeteCfgInfo *pFeteCfg = g_GetCampFeteCfgTable()->GetCampFeteCfgInfo(godType);
		if (nullptr == pFeteCfg)
		{
			return;
		}

		charCamp->GodsID(rsp.gods_id());
		SCampGodsInfo *cInfo = pCamp->GetGodsInfo(charCamp->GodsID());
		if (nullptr == cInfo)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CheckPrayCost nullptr = SCampGodsInfo ..godsId=%u failed...", rsp.gods_id());
			return;
		}
		cInfo->num++;

		uint32_t randTol = abs(pFeteCfg->minGain) + abs(pFeteCfg->maxGain);
		uint32_t randInt = Random(randTol);
		uint32_t curDevout = pPrayInfo->devout;
		if (randInt > (uint32_t)pFeteCfg->maxGain)
		{
			uint32_t del = randInt - pFeteCfg->maxGain;
			curDevout = (curDevout >= del) ? (curDevout - del) : 0;
		}
		else
		{
			uint32_t add = randInt;
			curDevout += add;
		}

		pPrayInfo->devout = curDevout;
		prayRsp.set_devout(curDevout);
		//Camp_PrayInfoNotify notify;
		//notify.set_gods_id(rsp.gods_id());
		//notify.set_devout(curDevout);
		//g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY_CHANGE, &notify);
		m_setCharacterCampNeedSave.insert(charID);
		charCamp->NeedSave(true);
		m_bCampNeedSave = true;
	}
	g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY, &prayRsp);
}

//逻辑服通知中心服事件
void CampMgr::LogicToCenter_Notify(RECV_PACKAGE &package)
{
	LogicToCenter_NotifyEvent notity;
	if (!notity.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_NotifyEvent parse failed...");
		return;
	}
	CharIDType charID = notity.char_id();

	switch (notity.type())
	{
	case ECamp_EventType_Pvp:
		KillEnemy(charID, notity.param1());
		break;
	case ECamp_EventType_LogicChangeCampSuccess:
		LogicChangeCamp(charID);
		break;
	default:
		break;
	}
}

//逻辑服通知中心服加阵营属性
void CampMgr::LogicToCenter_AddAttr(RECV_PACKAGE &package)
{
	LogicToCenter_AddCampAttr addAttr;
	if (!addAttr.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_AddAttr parse failed...");
		return;
	}
	uint32_t size = addAttr.camp_attr_size();
	for (uint32_t i = 0; i < size; i++)
	{
		const LogicToCenter_AddCampAttr::CampAttr &cAttr = addAttr.camp_attr(i);
		AddCampPrestige(cAttr.char_id(), cAttr.prestige());
	}
	
}

//逻辑服通知中心服挑战阵营结束
void CampMgr::LogicToCenter_CampChallenge(RECV_PACKAGE &package)
{
	GWArenaCampChallResult result;
	if (!result.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChallenge parse failed...");
		return;
	}

	Camp_ChallengeRsp rsp;
	rsp.set_is_win(false);

	CharIDType charId = result.srccharid();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChallenge nullptr == pOnline.. failed...");
		rsp.set_retcode(RET_FAIL);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChallenge nullptr == pOffline.. failed...");
		rsp.set_retcode(RET_FAIL);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChallenge nullptr == pCamp.. failed...campId:%d", pOffline->GetCampID());
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChallenge nullptr == charCamp.. failed...");
		rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
		return;
	}

	if (result.ret() == ACRE_WIN)
	{
		charCamp->ChallengeFlag(true);
		rsp.set_is_win(true);
	}
	else
	{
		charCamp->ChallengeFlag(false);
		rsp.set_is_win(false);
	}

	m_setCharacterCampNeedSave.insert(charId);
	charCamp->NeedSave(true);

	g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHALLENGE, &rsp);
}

//逻辑服通知中心服朝拜属性改变
void CampMgr::LogicToCenter_CampPushPrayInfo(RECV_PACKAGE &package)
{
	LogicToCenter_PushPrayAtt prayAtt;
	if (!prayAtt.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo parse failed...");
		return;
	}

	CharIDType charId = prayAtt.char_id();
	uint32_t godId = prayAtt.godid();
	uint32_t godType = prayAtt.godtype();
	ActiveCharacter *pOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnline)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr == pOnline.. failed...");
		return;
	}
	OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOffline)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr == pOffline.. failed...");
		return;
	}

	Camp *pCamp = GetCamp(pOffline->GetCampID());
	if (nullptr == pCamp)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr == pCamp.. failed...");
		return;
	}

	CharacterCamp *charCamp = GetCharacterCamp(charId);
	if (nullptr == charCamp)
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr == charCamp.. failed...");
		return;
	}

	int64_t att[10] = { 0 };
	size_t size = prayAtt.att_size();
	for (size_t i = 0; i != size; ++i)
	{
		const LogicToCenter_PushPrayAtt::Attr &pAttr = prayAtt.att(i);
		if (pAttr.attrid() < 1 || pAttr.attrid() > 6)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo pAttr.attrid() < 1 || pAttr.attrid() > 6");
			continue;
		}
		att[pAttr.attrid()] = pAttr.att();
	}

	if (prayAtt.type() == LogicToCenter_PushPrayAtt_Type_AttPush)
	{
		//升级和加点后朝拜属性更新
		LogicToCenter_CampAttChange attChange;
		attChange.set_char_id(charId);

		CampPrayInfoMap &prayMap = charCamp->GetPrayMap();
		for (CampPrayInfoMap::iterator ib = prayMap.begin(), ie = prayMap.end(); ib != ie; ++ib)
		{
			const CampGodsCfgInfo *pGodCfg = g_GetCampGodsCfgTable()->GetCampGodsCfgInfo(ib->first);
			if (nullptr == pGodCfg)
			{
				LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr == CampFeteCfgInfo *pCfg....godId:%d", ib->first);
				continue;
			}
			SCampPrayInfo &prayInfo = ib->second;
			for (MAP_UINT32_UINT32::iterator iterb = prayInfo.attrMap.begin(), itere = prayInfo.attrMap.end(); iterb != itere; ++iterb)
			{
				//1-6 位朝拜影响的一级C属性ID
				if (iterb->first < 1 || iterb->first > 6)
				{
					LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo ib->first < 1 || ib->first > 6");
					continue;
				}
				//计算升级、加点后的属性加成
				uint32_t addValue = (uint32_t)floor(att[iterb->first] * pGodCfg->attributeGain * prayInfo.devout / 10000.f);
				iterb->second = addValue;

				LogicToCenter_CampAttChange::Attr *pAttr = attChange.add_att();
				pAttr->set_attrid(iterb->first);
				pAttr->set_att(iterb->second);
			}
		}
		g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CAMP_ATT_CHANGE, &attChange);
	}
	else if (prayAtt.type() == LogicToCenter_PushPrayAtt_Type_PrayInfo)
	{
		SCampPrayInfo *pPrayInfo = charCamp->GetPray(godId);
		if (nullptr == pPrayInfo)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr == pPrayInfo.. failed...godId:%d", godId);
			return;
		}
		Camp_PrayAttrInfoRsp rsp;
		rsp.set_retcode(RET_SUCCESS);
		for (MAP_UINT32_UINT32::iterator ib = pPrayInfo->attrMap.begin(), ie = pPrayInfo->attrMap.end(); ib != ie; ++ib)
		{
			Camp_PrayAttrInfoRsp::Attr *pAttr = rsp.add_att();
			if (pAttr == nullptr)	continue;
			//1-6 位朝拜影响的一级C属性ID
			if (ib->first < 1 || ib->first > 6)
			{
				LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo ib->first < 1 || ib->first > 6");
				continue;
			}
			pAttr->set_attrid(ib->first);
			pAttr->set_attadd(ib->second);
			pAttr->set_attbase(att[ib->first]);
		}
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)SERVER_TO_CLIENT_CAMP_PRAY_INFO, &rsp);
	}
	else if (prayAtt.type() == LogicToCenter_PushPrayAtt_Type_PrayReq)
	{
		Camp_PrayRsp prayRsp;
		prayRsp.set_retcode(RET_SUCCESS);

		SCampPrayInfo *pPrayInfo = charCamp->GetPray(godId);
		if (nullptr == pPrayInfo)
		{
			prayRsp.set_retcode(RET_FAIL);
			g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY, &prayRsp);
			return;
		}

		const CampGodsCfgInfo *pGodCfg = g_GetCampGodsCfgTable()->GetCampGodsCfgInfo(godId);
		if (nullptr == pGodCfg)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr == CampFeteCfgInfo *pCfg....godId:%d", godId);
			prayRsp.set_retcode(RET_CONFIG_ERROR);
			g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY, &prayRsp);
			return;
		}
		const CampFeteCfgInfo *pFeteCfg = g_GetCampFeteCfgTable()->GetCampFeteCfgInfo(godType);
		if (nullptr == pFeteCfg)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr == CampFeteCfgInfo *pCfg....godType:%d", godType);
			prayRsp.set_retcode(RET_CONFIG_ERROR);
			g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY, &prayRsp);
			return;
		}

		if (charCamp->GodsID() != 0 && charCamp->GodsID() != godId)
		{
			prayRsp.set_retcode(RET_CAMP_PRAY_OTHER_GOD);
			g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY, &prayRsp);
			return;
		}

		charCamp->GodsID(godId);
		SCampGodsInfo *cInfo = pCamp->GetGodsInfo(charCamp->GodsID());
		if (nullptr == cInfo)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo nullptr = SCampGodsInfo ..godsId=%u failed...", godId);
		}
		else
			cInfo->num++;

		uint32_t add = 1;
		if (abs(pFeteCfg->maxGain) > abs(pFeteCfg->minGain))
			add = Random(abs(pFeteCfg->minGain), abs(pFeteCfg->maxGain));
		pPrayInfo->devout += add;
		pPrayInfo->devout = (pPrayInfo->devout >= CAMP_PRAY_MAX_DEVOUT) ? CAMP_PRAY_MAX_DEVOUT : pPrayInfo->devout;
		prayRsp.set_devout(pPrayInfo->devout);
		
		LogicToCenter_CampAttChange attChange;
		attChange.set_char_id(charId);

		for (MAP_UINT32_UINT32::iterator ib = pPrayInfo->attrMap.begin(), ie = pPrayInfo->attrMap.end(); ib != ie; ++ib)
		{
			//1-6 位朝拜影响的一级C属性ID
			if (ib->first < 1 || ib->first > 6)
			{
				LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampPushPrayInfo ib->first < 1 || ib->first > 6");
				continue;
			}
			//计算朝拜后的属性加成
			uint32_t addValue = (uint32_t)floor(att[ib->first] * pGodCfg->attributeGain * pPrayInfo->devout / 10000.f);
			ib->second = addValue;

			LogicToCenter_CampAttChange::Attr *pAttr = attChange.add_att();
			pAttr->set_attrid(ib->first);
			pAttr->set_att(ib->second);

			Camp_PrayRsp::Attr *pAtt = prayRsp.add_att();
			pAtt->set_attrid(ib->first);
			pAtt->set_attadd(ib->second);
			pAtt->set_attbase(att[ib->first]);
		}
		//通知逻辑服朝拜属性改变
		g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CAMP_ATT_CHANGE, &attChange);
		//朝拜返回
		g_GetCenterService()->SendDataToClient((CharIDType)charId, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY, &prayRsp);

		//通知逻辑服扣除道具
		CenterToLogic_CheckPrayCostReq checkReq;
		checkReq.set_char_id(charId);
		checkReq.set_gods_id(godId);
		checkReq.set_gods_type(godType);
		g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHECK_PRAY_COST_REQ, &checkReq);

		m_setCharacterCampNeedSave.insert(charId);
		charCamp->NeedSave(true);
	}
}

//逻辑服返回中心服验证更换阵营
void CampMgr::LogicToCenter_CampChangeCost(RECV_PACKAGE &package)
{
	LogicToCenter_CheckCampChangeRsp changeRsp;
	if (!changeRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost parse failed...");
		return;
	}

	uint64_t charID = changeRsp.char_id();
	Camp_ChangeRsp rsp;

	if (changeRsp.retcode() == RET_SUCCESS)
	{
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
		if (nullptr == pOffline)
		{
			rsp.set_retcode(RET_NOT_HAVE_CHARACTER);
			g_GetCenterService()->SendDataToClient(charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
			return;
		}

		CharacterCamp *pCharCamp = GetCharacterCamp(charID);
		if (nullptr == pCharCamp)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost ...nullptr == pCharCamp ... charid:%lu ", charID);
			rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
			g_GetCenterService()->SendDataToClient(charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
			return;
		}

		int8_t byCampID = pOffline->GetCampID();
		if (byCampID != ECamp_Type_Light && byCampID != ECamp_Type_Dark)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost ...byCampID != ECamp_Type_Light && byCampID != ECamp_Type_Dark..byCampID:%d", byCampID);
			rsp.set_retcode(RET_CAMP_NOT_JOIN_CAMP);
			g_GetCenterService()->SendDataToClient(charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
			return;
		}

		Camp *pCamp = GetCamp(byCampID);
		if (nullptr == pCamp)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost ...nullptr == pCamp ... charid:%lu,bycampid:%d  ", charID, byCampID);
			rsp.set_retcode(RET_CAMP_NOT_EXIST);
			g_GetCenterService()->SendDataToClient(charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
			return;
		}

		int8_t byChangeCampID = (byCampID == ECamp_Type_Light) ? ECamp_Type_Dark : ECamp_Type_Light;
		Camp *pChangeCamp = GetCamp(byChangeCampID);
		if (nullptr == pChangeCamp)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost ...nullptr == pChangeCamp ... charid:%lu,bycampid:%d  ", charID, byChangeCampID);
			rsp.set_retcode(RET_CAMP_NOT_EXIST);
			g_GetCenterService()->SendDataToClient(charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
			return;
		}

		SET_UINT64 *pMem = pCamp->Chars();
		if (nullptr == pMem)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost ...nullptr == pMem ... charid:%lu,bycampid:%d  ", charID, byCampID);
			rsp.set_retcode(RET_FAIL);
			g_GetCenterService()->SendDataToClient(charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
			return;
		}

		SET_UINT64 *pChangeMem = pChangeCamp->Chars();
		if (nullptr == pChangeMem)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost ...nullptr == pChangeMem ... charid:%lu,bycampid:%d  ", charID, byChangeCampID);
			rsp.set_retcode(RET_FAIL);
			g_GetCenterService()->SendDataToClient(charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
			return;
		}

		//通知逻辑服更新角色阵营信息
		CenterToLogic_CampCharInfo notify;
		notify.set_charid(charID);
		notify.add_attr_id(C_CAMP_ID);
		notify.add_attr_value(byChangeCampID);
		const CampFree_choiceCfgInfo *info = g_GetCampFree_choiceCfgTable()->GetCampFree_choiceCfgInfo(pChangeCamp->ConfigID());
		if (info)
		{
			notify.add_attr_id(C_OFFICIAL);
			notify.add_attr_value(info->initialOfficial);
			notify.add_attr_id(C_KNIGHT);
			notify.add_attr_value(info->initiaKnighthood);
			notify.add_attr_id(C_CAMP_SCORE);
			notify.add_attr_value(0);
			notify.add_attr_id(C_CAMP_COIN);
			notify.add_attr_value(0);
			notify.add_attr_id(C_CAMP_PRESTIGE);
			notify.add_attr_value(0);
			notify.add_attr_id(C_CAMP_KILLERS);
			notify.add_attr_value(0);
		}

		if (!g_GetCenterService()->SendDataToLogicByCharID(charID, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CHAR_INFO_NOTIFY, &notify))
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost...SendDataToLogicByCharID failed.. byCampID:%d,charid:%lu ", byCampID, charID);
			//return;
		}

		pMem->erase(charID);
		pOffline->ClearCamp();
		pCharCamp->Clear();

		pOffline->SetCampID(byChangeCampID);
		pCharCamp->CharID(charID);

		//更新朝拜信息
		{
			//更换阵营后 清空阵营朝拜的属性加成
			LogicToCenter_CampAttChange attChange;
			attChange.set_char_id(charID);
			CampPrayInfoMap &prayMap = pCharCamp->GetPrayMap();
			for (CampPrayInfoMap::iterator ib = prayMap.begin(), ie = prayMap.end(); ib != ie; ++ib)
			{
				SCampPrayInfo &prayInfo = ib->second;
				for (MAP_UINT32_UINT32::iterator iterb = prayInfo.attrMap.begin(), itere = prayInfo.attrMap.end(); iterb != itere; ++iterb)
				{
					//1-6 位朝拜影响的一级C属性ID
					if (iterb->first < 1 || iterb->first > 6)
					{
						LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost ib->first < 1 || ib->first > 6");
						continue;
					}
					LogicToCenter_CampAttChange::Attr *pAttr = attChange.add_att();
					pAttr->set_attrid(iterb->first);
					pAttr->set_att(0);
				}
			}
			g_GetCenterService()->SendDataToLogicByCharID(charID, EMODULE_ID_CAMP, CENTER_TO_LOGIC_CAMP_CAMP_ATT_CHANGE, &attChange);

			//更换阵营后 重置朝拜信息
			pCharCamp->Init(pChangeCamp->ConfigID());

			Camp_PrayInfoNotify notify;
			notify.set_gods_id(pCharCamp->GodsID());
			prayMap = pCharCamp->GetPrayMap();
			for (CampPrayInfoMap::iterator ib = prayMap.begin(), ie = prayMap.end(); ib != ie; ++ib)
			{
				SCampPrayInfo &prayInfo = ib->second;
				CampProtoPrayInfo *pPrayProto = notify.add_pray_info();
				pPrayProto->set_godid(ib->first);
				pPrayProto->set_devout(prayInfo.devout);
			}
			g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_PRAY_CHANGE, &notify);
		}

		if (info)
		{
			pOffline->SetOfficial(info->initialOfficial);
			pOffline->SetKnight(info->initiaKnighthood);
		}

		uint64_t nCurSec = g_GetGlobalServerTime()->UnixSec();
		pCharCamp->LastJoin(nCurSec);
		pChangeMem->insert(charID);
		OfflineCharacterData *pLeaderOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(pChangeCamp->LeaderID());
		CampProtoInfo protoInfo;
		protoInfo.set_camp_id((int32_t)pChangeCamp->CampID());
		protoInfo.set_dividend_flag(pCharCamp->DividendFlag());
		if (nullptr != pLeaderOffline)
		{
			protoInfo.set_leader_name(pLeaderOffline->GetCharName());
		}
		protoInfo.set_notice(pChangeCamp->Notice());
		uint64_t changeTick = nCurSec + CampChangeCDTime;
		pCharCamp->ChangeTick(changeTick);
		protoInfo.set_change_camp_tick(changeTick);
		if (charID == pChangeCamp->LeaderID())
		{
			uint64_t nLast = pChangeCamp->LastNotice();
			uint64_t nInterSec = ((nCurSec - nLast) >= CampNoticeCDTime) ? 0 : (CampNoticeCDTime - (nCurSec - nLast));
			nInterSec += nCurSec;
			protoInfo.set_notice_cd(nInterSec);
		}
		g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_INFO_CHANGE, &protoInfo);

		pCamp->DelChars(pOffline);
		pCamp->DelCandi(charID);	//退出竞选
		pChangeCamp->AddChars(pOffline);

		//阵营首领更换阵营
		if (charID == pCamp->LeaderID())
		{
			pCamp->LeaderID(0);
			UpdateCampLeaderToLogic(pCamp->CampID());
		}

		g_GetTeamMgr()->QuitTeam(charID);
		g_GetRelationMgr()->CampChange(pOffline);

		//更换阵营成功同时退出公会
		CUnion *quitUnion = g_GetUnionMgr()->QuitUnion(charID);
		if (quitUnion != nullptr)
		{
			LogErrFmtPrint("[center] CampMgr::LogicToCenter_CampChangeCost...after change camp, player should quit union ..error....unioName:%s, charName:%s", quitUnion->Name(), pOffline->GetCharName());
		}

		m_setCharacterCampNeedSave.insert(charID);
		pCharCamp->NeedSave(true);
		m_bCampNeedSave = true;
	}

	rsp.set_retcode(changeRsp.retcode());
	g_GetCenterService()->SendDataToClient((CharIDType)charID, (uint16_t)EMODULE_ID_CAMP, (uint16_t)CENTER_TO_CLIENT_CAMP_CHANGE, &rsp);
}
